Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcutil / silcbuffer.h
index a6ca1897e2fc3444e7650aa4566874a2da303b04..4dc1472ae6822fc5bff68575c5db519c7e0c3604 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  silcbuffer.h
+  silcbuffer.h 
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1998 - 2000 Pekka Riikonen
+  Copyright (C) 1998 - 2002 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #ifndef SILCBUFFER_H
 #define SILCBUFFER_H
 
-/* 
-   SILC Buffer object.
-
-   SilcBuffer is very simple and easy to use, yet you can do to the
-   buffer almost anything you want with its method functions. The buffer
-   is constructed of four different data sections that in whole creates
-   the allocated data area. Following short description of the fields
-   of the buffer.
-
-   uint32 truelen;
-
-       True length of the buffer. This is set at the allocation of the
-       buffer and it should not be touched after that. This field should
-       be considered read-only.
-
-   uint32 len;
-
-       Length of the currently valid data area. Tells the length of the 
-       data at the buffer. This is set to zero at the allocation of the
-       buffer and should not be updated by hand. Method functions of the
-       buffer automatically updates this field. However, it is not
-       read-only field and can be updated manually if necessary.
-
-   unsiged char *head;
-
-       Head of the allocated buffer. This is the start of the allocated
-       data area and remains as same throughout the lifetime of the buffer.
-       However, the end of the head area or the start of the currently valid
-       data area is variable.
-
-       --------------------------------
-       | head  | data         | tail  |
-       --------------------------------
-       ^       ^
-
-       Current head section in the buffer is sb->data - sb->head.
-
-   unsigned char *data;
-
-       Currently valid data area. This is the start of the currently valid
-       main data area. The data area is variable in all directions.
-
-       --------------------------------
-       | head  | data         | tail  |
-       --------------------------------
-               ^              ^
-       Current valid data area in the buffer is sb->tail - sb->data.
-
-    unsigned char *tail;
-
-       Tail of the buffer. This is the end of the currently valid data area
-       or start of the tail area. The start of the tail area is variable.
-
-       --------------------------------
-       | head  | data         | tail  |
-       --------------------------------
-                              ^       ^
-
-       Current tail section in the buffer is sb->end - sb->tail.
-
-   unsigned char *end;
-
-       End of the allocated buffer. This is the end of the allocated data
-       area and remains as same throughout the lifetime of the buffer.
-       Usually this field is not needed except when checking the size
-       of the buffer.
-
-       --------------------------------
-       | head  | data         | tail  |
-       --------------------------------
-                                      ^
-
-       Length of the entire buffer is (ie. truelen) sb->end - sb->head.
-
-    Currently valid data area is considered to be the main data area in
-    the buffer. However, the entire buffer is of course valid data and can
-    be used as such. Usually head section of the buffer includes different
-    kind of headers or similiar. Data section includes the main data of
-    the buffer. Tail section can be seen as a reserve space of the data
-    section. Tail section can be pulled towards end thus the data section
-    becomes larger.
-
-    This buffer scheme is based on Linux kernel's Socket Buffer, the 
-    idea were taken directly from there and credits should go there.
-
-*/
-
+/****h* silcutil/SILC Buffer Interface
+ *
+ * DESCRIPTION
+ *
+ *    SilcBuffer is very simple and easy to use, yet you can do to the
+ *    buffer almost anything you want with its method functions. The buffer
+ *    is constructed of four different data sections that in whole creates
+ *    the allocated data area.
+ *
+ *    This buffer scheme is based on Linux kernel's Socket Buffer, the
+ *    idea were taken directly from there and credits should go there.
+ *
+ ***/
+
+/****s* silcutil/SilcBufferAPI/SilcBuffer
+ *
+ * NAME
+ *
+ *    typedef struct { ... } *SilcBuffer, SilcBufferStruct;
+ *
+ * DESCRIPTION
+ *
+ *    SILC Buffer object. Following short description of the fields
+ *    of the buffer.
+ *
+ * EXAMPLE
+ *
+ *    SilcUInt32 truelen;
+ *
+ *        True length of the buffer. This is set at the allocation of the
+ *        buffer and it should not be touched after that. This field should
+ *        be considered read-only.
+ *
+ *    SilcUInt32 len;
+ *
+ *        Length of the currently valid data area. Tells the length of the
+ *        data at the buffer. This is set to zero at the allocation of the
+ *        buffer and should not be updated by hand. Method functions of the
+ *        buffer automatically updates this field. However, it is not
+ *        read-only field and can be updated manually if necessary.
+ *
+ *    unsiged char *head;
+ *
+ *        Head of the allocated buffer. This is the start of the allocated
+ *        data area and remains as same throughout the lifetime of the buffer.
+ *        However, the end of the head area or the start of the currently valid
+ *        data area is variable.
+ *
+ *        --------------------------------
+ *        | head  | data         | tail  |
+ *        --------------------------------
+ *        ^       ^
+ *
+ *        Current head section in the buffer is sb->data - sb->head.
+ *
+ *    unsigned char *data;
+ *
+ *        Currently valid data area. This is the start of the currently valid
+ *        main data area. The data area is variable in all directions.
+ *
+ *        --------------------------------
+ *        | head  | data         | tail  |
+ *        --------------------------------
+ *                ^              ^
+ *
+ *        Current valid data area in the buffer is sb->tail - sb->data.
+ *
+ *     unsigned char *tail;
+ *
+ *        Tail of the buffer. This is the end of the currently valid data area
+ *        or start of the tail area. The start of the tail area is variable.
+ *
+ *        --------------------------------
+ *        | head  | data         | tail  |
+ *        --------------------------------
+ *                               ^       ^
+ *
+ *        Current tail section in the buffer is sb->end - sb->tail.
+ *
+ *    unsigned char *end;
+ *
+ *        End of the allocated buffer. This is the end of the allocated data
+ *        area and remains as same throughout the lifetime of the buffer.
+ *        Usually this field is not needed except when checking the size
+ *        of the buffer.
+ *
+ *        --------------------------------
+ *        | head  | data         | tail  |
+ *        --------------------------------
+ *                                       ^
+ *
+ *        Length of the entire buffer is (ie. truelen) sb->end - sb->head.
+ *
+ *     Currently valid data area is considered to be the main data area in
+ *     the buffer. However, the entire buffer is of course valid data and can
+ *     be used as such. Usually head section of the buffer includes different
+ *     kind of headers or similar. Data section includes the main data of
+ *     the buffer. Tail section can be seen as a reserve space of the data
+ *     section. Tail section can be pulled towards end, and thus the data
+ *     section becomes larger.
+ *
+ * SOURCE
+ */
 typedef struct {
-  uint32 truelen;
-  uint32 len;
+  SilcUInt32 truelen;
+  SilcUInt32 len;
   unsigned char *head;
   unsigned char *data;
   unsigned char *tail;
   unsigned char *end;
 } *SilcBuffer, SilcBufferStruct;
+/***/
 
 /* Macros */
 
-/* Returns the true length of the buffer. This is used to pull
-   the buffer area to the end of the buffer. */
+/****d* silcutil/SilcBufferAPI/SILC_BUFFER_END
+ * 
+ * NAME
+ *
+ *    #define SILC_BUFFER_END(...)
+ *
+ * DESCRIPTION
+ *
+ *    Returns the true length of the buffer. This is used to pull
+ *    the buffer area to the end of the buffer.
+ *
+ * SOURCE
+ */
 #define SILC_BUFFER_END(x) ((x)->end - (x)->head)
+/***/
 
 /* Inline functions */
 
-extern inline
-SilcBuffer silc_buffer_alloc(uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_alloc
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBuffer silc_buffer_alloc(SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Allocates new SilcBuffer and returns it.
+ *
+ ***/
+static inline
+SilcBuffer silc_buffer_alloc(SilcUInt32 len)
 {
   SilcBuffer sb;
 
   /* Allocate new SilcBuffer */
   sb = (SilcBuffer)silc_calloc(1, sizeof(*sb));
+  if (!sb)
+    return NULL;
 
   /* Allocate the actual data area */
   sb->head = (unsigned char *)silc_calloc(len, sizeof(*sb->head));
+  if (!sb->head)
+    return NULL;
 
   /* Set pointers to the new buffer */
   sb->truelen = len;
@@ -148,55 +192,121 @@ SilcBuffer silc_buffer_alloc(uint32 len)
   return sb;
 }
 
-/* Free's a SilcBuffer */
-
-extern inline
+/****f* silcutil/SilcBufferAPI/silc_buffer_free
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_buffer_free(SilcBuffer sb);
+ *
+ * DESCRIPTION
+ *
+ *    Frees SilcBuffer.
+ *
+ ***/
+
+static inline
 void silc_buffer_free(SilcBuffer sb)
 {
   if (sb) {
-    memset(sb->head, 'F', sb->truelen);
+#if defined(SILC_DEBUG)
+    if (sb->head)
+      memset(sb->head, 'F', sb->truelen);
+#endif
     silc_free(sb->head);
     silc_free(sb);
   }
 }
 
-/* Sets the `data' and `data_len' to the buffer pointer sent as argument.
-   The data area is automatically set to the `data_len'. This function
-   can be used to set the data to static buffer without needing any
-   memory allocations. The `data' will not be copied to the buffer. */
+/****f* silcutil/SilcBufferAPI/silc_buffer_steal
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len);
+ *
+ * DESCRIPTION
+ *
+ *    Steals the data from the buffer `sb'.  This returns pointer to the
+ *    start of the buffer and the true length of that buffer.  The `sb'
+ *    cannot be used anymore after calling this function because the
+ *    data buffer was stolen.  The `sb' must be freed with silc_buffer_free.
+ *    The caller is responsible of freeing the stolen data buffer with
+ *    silc_free.
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
+{
+  unsigned char *buf = sb->head;
+  if (data_len)
+    *data_len = sb->truelen;
+  sb->head = sb->data = sb->tail = sb->end = NULL;
+  sb->len = sb->truelen = 0;
+  return buf;
+}
 
-extern inline
-void silc_buffer_set(SilcBuffer sb, unsigned char *data, uint32 data_len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_set
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_buffer_set(SilcBuffer sb,
+ *                        unsigned char *data,
+ *                         SilcUInt32 data_len);
+ *
+ * DESCRIPTION
+ *
+ *    Sets the `data' and `data_len' to the buffer pointer sent as argument.
+ *    The data area is automatically set to the `data_len'. This function
+ *    can be used to set the data to static buffer without needing any
+ *    memory allocations. The `data' will not be copied to the buffer.
+ *
+ ***/
+
+static inline
+void silc_buffer_set(SilcBuffer sb, unsigned char *data, SilcUInt32 data_len)
 {
   sb->data = sb->head = data;
   sb->tail = sb->end = data + data_len;
   sb->len = sb->truelen = data_len;
 }
 
-/* Pulls current data area towards end. The length of the currently
-   valid data area is also decremented. Returns pointer to the data
-   area before pulling. 
-
-   Example:
-   ---------------------------------
-   | head  | data       | tail     |
-   ---------------------------------
-           ^
-           Pulls the start of the data area.
-
-   ---------------------------------
-   | head     | data    | tail     |
-   ---------------------------------
-           ^
-*/
-
-extern inline 
-unsigned char *silc_buffer_pull(SilcBuffer sb, uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_pull
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Pulls current data area towards end. The length of the currently
+ *    valid data area is also decremented. Returns pointer to the data
+ *    area before pulling.
+ *
+ * EXAMPLE
+ *
+ *    ---------------------------------
+ *    | head  | data       | tail     |
+ *    ---------------------------------
+ *            ^
+ *            Pulls the start of the data area.
+ *
+ *    ---------------------------------
+ *    | head     | data    | tail     |
+ *    ---------------------------------
+ *            ^
+ ***/
+
+static inline
+unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_data = sb->data;
 
-#ifdef SILC_DEBUG
-  assert(len <= (sb->tail - sb->data));
+#if defined(SILC_DEBUG)
+  assert(len <= (SilcUInt32)(sb->tail - sb->data));
 #endif
 
   sb->data += len;
@@ -205,29 +315,40 @@ unsigned char *silc_buffer_pull(SilcBuffer sb, uint32 len)
   return old_data;
 }
 
-/* Pushes current data area towards beginning. Length of the currently
-   valid data area is also incremented. Returns a pointer to the 
-   data area before pushing. 
-
-   Example:
-   ---------------------------------
-   | head     | data    | tail     |
-   ---------------------------------
-              ^
-              Pushes the start of the data area.
-
-   ---------------------------------
-   | head  | data       | tail     |
-   ---------------------------------
-              ^
-*/
-
-extern inline 
-unsigned char *silc_buffer_push(SilcBuffer sb, uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_push
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Pushes current data area towards beginning. Length of the currently
+ *    valid data area is also incremented. Returns a pointer to the 
+ *    data area before pushing. 
+ *
+ * EXAMPLE
+ *
+ *    ---------------------------------
+ *    | head     | data    | tail     |
+ *    ---------------------------------
+ *               ^
+ *               Pushes the start of the data area.
+ *
+ *    ---------------------------------
+ *    | head  | data       | tail     |
+ *    ---------------------------------
+ *               ^
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_data = sb->data;
 
-#ifdef SILC_DEBUG
+#if defined(SILC_DEBUG)
   assert((sb->data - len) >= sb->head);
 #endif
 
@@ -237,30 +358,41 @@ unsigned char *silc_buffer_push(SilcBuffer sb, uint32 len)
   return old_data;
 }
 
-/* Pulls current tail section towards end. Length of the current valid
-   data area is also incremented. Returns a pointer to the data area 
-   before pulling.
-
-   Example:
-   ---------------------------------
-   | head  | data       | tail     |
-   ---------------------------------
-                        ^
-                        Pulls the start of the tail section.
-
-   ---------------------------------
-   | head  | data           | tail |
-   ---------------------------------
-                        ^
-*/
-
-extern inline 
-unsigned char *silc_buffer_pull_tail(SilcBuffer sb, uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_pull_tail
+ *
+ * SYNOPSIS
+ *
+ *    static inline 
+ *    unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Pulls current tail section towards end. Length of the current valid
+ *    data area is also incremented. Returns a pointer to the data area 
+ *    before pulling.
+ *
+ * EXAMPLE
+ *
+ *    ---------------------------------
+ *    | head  | data       | tail     |
+ *    ---------------------------------
+ *                         ^
+ *                         Pulls the start of the tail section.
+ *
+ *    ---------------------------------
+ *    | head  | data           | tail |
+ *    ---------------------------------
+ *                         ^
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_tail = sb->tail;
 
-#ifdef SILC_DEBUG
-  assert((sb->end - sb->tail) >= len);
+#if defined(SILC_DEBUG)
+  assert((SilcUInt32)(sb->end - sb->tail) >= len);
 #endif
 
   sb->tail += len;
@@ -269,29 +401,40 @@ unsigned char *silc_buffer_pull_tail(SilcBuffer sb, uint32 len)
   return old_tail;
 }
 
-/* Pushes current tail section towards beginning. Length of the current
-   valid data area is also decremented. Returns a pointer to the 
-   tail section before pushing. 
-
-   Example:
-   ---------------------------------
-   | head  | data           | tail |
-   ---------------------------------
-                            ^
-                            Pushes the start of the tail section.
-
-   ---------------------------------
-   | head  | data       | tail     |
-   ---------------------------------
-                            ^
-*/
-
-extern inline
-unsigned char *silc_buffer_push_tail(SilcBuffer sb, uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_push_tail
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Pushes current tail section towards beginning. Length of the current
+ *    valid data area is also decremented. Returns a pointer to the
+ *    tail section before pushing.
+ *
+ * EXAMPLE
+ *
+ *    ---------------------------------
+ *    | head  | data           | tail |
+ *    ---------------------------------
+ *                             ^
+ *                             Pushes the start of the tail section.
+ *
+ *    ---------------------------------
+ *    | head  | data       | tail     |
+ *    ---------------------------------
+ *                             ^
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_tail = sb->tail;
 
-#ifdef SILC_DEBUG
+#if defined(SILC_DEBUG)
   assert((sb->tail - len) >= sb->data);
 #endif
 
@@ -301,70 +444,257 @@ unsigned char *silc_buffer_push_tail(SilcBuffer sb, uint32 len)
   return old_tail;
 }
 
-/* Puts data at the head of the buffer. Returns pointer to the copied
-   data area. 
-   
-   Example:
-   ---------------------------------
-   | head  | data       | tail     |
-   ---------------------------------
-   ^
-   Puts data to the head section. 
-*/
-
-extern inline
-unsigned char *silc_buffer_put_head(SilcBuffer sb, 
-                                   unsigned char *data,
-                                   uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_put_head
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_put_head(SilcBuffer sb, 
+ *                                       const unsigned char *data,
+ *                                       SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Puts data at the head of the buffer. Returns pointer to the copied
+ *    data area. 
+ *
+ * EXAMPLE
+ *
+ *    ---------------------------------
+ *    | head  | data       | tail     |
+ *    ---------------------------------
+ *    ^
+ *    Puts data to the head section. 
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_put_head(SilcBuffer sb,
+                                   const unsigned char *data,
+                                   SilcUInt32 len)
 {
-#ifdef SILC_DEBUG
-  assert((sb->data - sb->head) >= len);
+#if defined(SILC_DEBUG)
+  assert((SilcUInt32)(sb->data - sb->head) >= len);
 #endif
   return (unsigned char *)memcpy(sb->head, data, len);
 }
 
-/* Puts data at the start of the valid data area. Returns a pointer 
-   to the copied data area. 
-
-   Example:
-   ---------------------------------
-   | head  | data       | tail     |
-   ---------------------------------
-           ^
-           Puts data to the data section.
-*/
-
-extern inline
-unsigned char *silc_buffer_put(SilcBuffer sb, 
-                              unsigned char *data,
-                              uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_put
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_put(SilcBuffer sb,
+ *                                  const unsigned char *data,
+ *                                  SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Puts data at the start of the valid data area. Returns a pointer
+ *    to the copied data area.
+ *
+ * EXAMPLE
+ *
+ *    ---------------------------------
+ *    | head  | data       | tail     |
+ *    ---------------------------------
+ *            ^
+ *            Puts data to the data section.
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_put(SilcBuffer sb,
+                              const unsigned char *data,
+                              SilcUInt32 len)
 {
-#ifdef SILC_DEBUG
-  assert((sb->tail - sb->data) >= len);
+#if defined(SILC_DEBUG)
+  assert((SilcUInt32)(sb->tail - sb->data) >= len);
 #endif
   return (unsigned char *)memcpy(sb->data, data, len);
 }
 
-/* Puts data at the tail of the buffer. Returns pointer to the copied
-   data area. 
-
-   Example:
-   ---------------------------------
-   | head  | data           | tail |
-   ---------------------------------
-                            ^
-                           Puts data to the tail section.
-*/
-
-extern inline
-unsigned char *silc_buffer_put_tail(SilcBuffer sb, 
-                                   unsigned char *data,
-                                   uint32 len)
+/****f* silcutil/SilcBufferAPI/silc_buffer_put_tail
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_put_tail(SilcBuffer sb,
+ *                                       const unsigned char *data,
+ *                                       SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Puts data at the tail of the buffer. Returns pointer to the copied
+ *    data area. 
+ *
+ * EXAMPLE
+ *
+ *    ---------------------------------
+ *    | head  | data           | tail |
+ *    ---------------------------------
+ *                             ^
+ *                            Puts data to the tail section.
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_put_tail(SilcBuffer sb,
+                                   const unsigned char *data,
+                                   SilcUInt32 len)
 {
-#ifdef SILC_DEBUG
-  assert((sb->end - sb->tail) >= len);
+#if defined(SILC_DEBUG)
+  assert((SilcUInt32)(sb->end - sb->tail) >= len);
 #endif
   return (unsigned char *)memcpy(sb->tail, data, len);
 }
 
+/****f* silcutil/SilcBufferAPI/silc_buffer_alloc_size
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBuffer silc_buffer_alloc_size(SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Allocates `len' bytes size buffer and moves the tail area automatically
+ *    `len' bytes so that the buffer is ready to use without calling the
+ *    silc_buffer_pull_tail.
+ *
+ ***/
+
+static inline
+SilcBuffer silc_buffer_alloc_size(SilcUInt32 len)
+{
+  SilcBuffer sb = silc_buffer_alloc(len);
+  if (!sb)
+    return NULL;
+  silc_buffer_pull_tail(sb, len);
+  return sb;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_clear
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    void silc_buffer_clear(SilcBuffer sb);
+ *
+ * DESCRIPTION
+ *
+ *    Clears and initialiazes the buffer to the state as if it was just
+ *    allocated by silc_buffer_alloc.
+ *
+ ***/
+
+static inline
+void silc_buffer_clear(SilcBuffer sb)
+{
+  if (!sb)
+    return;
+  memset(sb->head, 0, sb->truelen);
+  sb->data = sb->head;
+  sb->tail = sb->head;
+  sb->len = 0;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_copy
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBuffer silc_buffer_copy(SilcBuffer sb);
+ *
+ * DESCRIPTION
+ *
+ *    Generates copy of a SilcBuffer. This copies everything inside the
+ *    currently valid data area, nothing more. Use silc_buffer_clone to
+ *    copy entire buffer.
+ *
+ ***/
+
+static inline
+SilcBuffer silc_buffer_copy(SilcBuffer sb)
+{
+  SilcBuffer sb_new;
+
+  sb_new = silc_buffer_alloc_size(sb->len);
+  if (!sb_new)
+    return NULL;
+  silc_buffer_put(sb_new, sb->data, sb->len);
+
+  return sb_new;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_clone
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBuffer silc_buffer_clone(SilcBuffer sb);
+ *
+ * DESCRIPTION
+ *
+ *    Clones SilcBuffer. This generates new SilcBuffer and copies
+ *    everything from the source buffer. The result is exact clone of
+ *    the original buffer.
+ *
+ ***/
+
+static inline
+SilcBuffer silc_buffer_clone(SilcBuffer sb)
+{
+  SilcBuffer sb_new;
+
+  sb_new = silc_buffer_alloc_size(sb->truelen);
+  if (!sb_new)
+    return NULL;
+  silc_buffer_put(sb_new, sb->head, sb->truelen);
+  sb_new->data = sb_new->head + (sb->data - sb->head);
+  sb_new->tail = sb_new->data + sb->len;
+  sb_new->len = sb->len;
+
+  return sb_new;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_realloc
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize);
+ *
+ * DESCRIPTION
+ *
+ *    Reallocates buffer. Old data is saved into the new buffer. Returns
+ *    new SilcBuffer pointer. The buffer is exact clone of the old one
+ *    except that there is now more space at the end of buffer.
+ *
+ ***/
+
+static inline
+SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize)
+{
+  SilcBuffer sb_new;
+
+  if (!sb)
+    return silc_buffer_alloc(newsize);
+
+  if (newsize <= sb->truelen)
+    return sb;
+
+  sb_new = silc_buffer_alloc_size(newsize);
+  if (!sb_new)
+    return NULL;
+  silc_buffer_put(sb_new, sb->head, sb->truelen);
+  sb_new->data = sb_new->head + (sb->data - sb->head);
+  sb_new->tail = sb_new->data + sb->len;
+  sb_new->len = sb->len;
+
+  silc_buffer_free(sb);
+
+  return sb_new;
+}
+
 #endif