Added SILC errno API. Added SilcResult, generic error code and
[crypto.git] / lib / silcutil / silcbuffer.h
index 5fb70b84ffafb515387d4d3d82dceeef5c06eb41..30f11dc344d7c9177988f2d3a9ba79e528abb751 100644 (file)
@@ -238,7 +238,8 @@ SilcUInt32 silc_buffer_taillen(SilcBuffer x)
  *
  * DESCRIPTION
  *
- *    Allocates new SilcBuffer and returns it.  Returns NULL on error.
+ *    Allocates new SilcBuffer and returns it.  Returns NULL if system is
+ *    out of memory.
  *
  ***/
 
@@ -276,7 +277,8 @@ SilcBuffer silc_buffer_alloc(SilcUInt32 len)
  *
  * DESCRIPTION
  *
- *    Allocates new SilcBuffer and returns it.
+ *    Allocates new SilcBuffer and returns it.  Returns NULL if system is
+ *    out of memory.
  *
  *    This routine use SilcStack are memory source.  If `stack' is NULL
  *    reverts back to normal allocating routine.
@@ -503,7 +505,8 @@ void silc_buffer_set(SilcBuffer sb, unsigned char *data, SilcUInt32 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. Returns NULL on error.
+ *    area before pulling. Returns NULL if the pull would lead to buffer
+ *    overflow or would go beyond the valid data area.
  *
  * EXAMPLE
  *
@@ -526,12 +529,15 @@ static inline
 unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_data = sb->data;
-#if defined(SILC_DEBUG)
+
+#ifdef SILC_DIST_INPLACE
   SILC_ASSERT(len <= silc_buffer_len(sb));
-#else
-  if (silc_unlikely(len > silc_buffer_len(sb)))
+#endif /* SILC_DIST_INPLACE */
+  if (silc_unlikely(len > silc_buffer_len(sb))) {
+    silc_set_errno(SILC_ERR_OVERFLOW);
     return NULL;
-#endif
+  }
+
   sb->data += len;
   return old_data;
 }
@@ -547,7 +553,8 @@ unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len)
  *
  *    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. Returns NULL on error.
+ *    data area before pushing. Returns NULL if the push would lead to
+ *    buffer underflow or would go under the valid data area.
  *
  * EXAMPLE
  *
@@ -570,12 +577,15 @@ static inline
 unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_data = sb->data;
-#if defined(SILC_DEBUG)
+
+#ifdef SILC_DIST_INPLACE
   SILC_ASSERT((sb->data - len) >= sb->head);
-#else
-  if (silc_unlikely((sb->data - len) < sb->head))
+#endif /* SILC_DIST_INPLACE */
+  if (silc_unlikely((sb->data - len) < sb->head)) {
+    silc_set_errno(SILC_ERR_UNDERFLOW);
     return NULL;
-#endif
+  }
+
   sb->data -= len;
   return old_data;
 }
@@ -591,7 +601,7 @@ unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len)
  *
  *    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. Returns NULL on error.
+ *    before pulling. Returns NULL if the pull would lead to buffer overflow.
  *
  * EXAMPLE
  *
@@ -614,12 +624,15 @@ static inline
 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_tail = sb->tail;
-#if defined(SILC_DEBUG)
+
+#ifdef SILC_DIST_INPLACE
   SILC_ASSERT(len <= silc_buffer_taillen(sb));
-#else
-  if (silc_unlikely(len > silc_buffer_taillen(sb)))
+#endif /* SILC_DIST_INPLACE */
+  if (silc_unlikely(len > silc_buffer_taillen(sb))) {
+    silc_set_errno(SILC_ERR_OVERFLOW);
     return NULL;
-#endif
+  }
+
   sb->tail += len;
   return old_tail;
 }
@@ -635,7 +648,8 @@ unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len)
  *
  *    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. Returns NULL on error.
+ *    tail section before pushing. Returns NULL if the push would lead to
+ *    buffer underflow or go under valid tail area.
  *
  * EXAMPLE
  *
@@ -658,12 +672,15 @@ static inline
 unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len)
 {
   unsigned char *old_tail = sb->tail;
-#if defined(SILC_DEBUG)
+
+#ifdef SILC_DIST_INPLACE
   SILC_ASSERT((sb->tail - len) >= sb->data);
-#else
-  if (silc_unlikely((sb->tail - len) < sb->data))
+#endif /* SILC_DIST_INPLACE */
+  if (silc_unlikely((sb->tail - len) < sb->data)) {
+    silc_set_errno(SILC_ERR_UNDERFLOW);
     return NULL;
-#endif
+  }
+
   sb->tail -= len;
   return old_tail;
 }
@@ -680,7 +697,8 @@ unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len)
  * DESCRIPTION
  *
  *    Puts data at the head of the buffer. Returns pointer to the copied
- *    data area. Returns NULL on error.
+ *    data area. Returns NULL if the data is longer that the current head
+ *    area.
  *
  * EXAMPLE
  *
@@ -699,12 +717,14 @@ unsigned char *silc_buffer_put_head(SilcBuffer sb,
                                    const unsigned char *data,
                                    SilcUInt32 len)
 {
-#if defined(SILC_DEBUG)
+#ifdef SILC_DIST_INPLACE
   SILC_ASSERT(len <= silc_buffer_headlen(sb));
-#else
-  if (silc_unlikely(len > silc_buffer_headlen(sb)))
+#endif /* SILC_DIST_INPLACE */
+  if (silc_unlikely(len > silc_buffer_headlen(sb))) {
+    silc_set_errno(SILC_ERR_OVERFLOW);
     return NULL;
-#endif
+  }
+
   return (unsigned char *)memcpy(sb->head, data, len);
 }
 
@@ -720,7 +740,8 @@ unsigned char *silc_buffer_put_head(SilcBuffer sb,
  * DESCRIPTION
  *
  *    Puts data at the start of the valid data area. Returns a pointer
- *    to the copied data area.  Returns NULL on error.
+ *    to the copied data area.  Returns NULL if the data is longer than the
+ *    current data area.
  *
  * EXAMPLE
  *
@@ -739,12 +760,14 @@ unsigned char *silc_buffer_put(SilcBuffer sb,
                               const unsigned char *data,
                               SilcUInt32 len)
 {
-#if defined(SILC_DEBUG)
+#ifdef SILC_DIST_INPLACE
   SILC_ASSERT(len <= silc_buffer_len(sb));
-#else
-  if (silc_unlikely(len > silc_buffer_len(sb)))
+#endif /* SILC_DIST_INPLACE */
+  if (silc_unlikely(len > silc_buffer_len(sb))) {
+    silc_set_errno(SILC_ERR_OVERFLOW);
     return NULL;
-#endif
+  }
+
   return (unsigned char *)memcpy(sb->data, data, len);
 }
 
@@ -760,7 +783,8 @@ unsigned char *silc_buffer_put(SilcBuffer sb,
  * DESCRIPTION
  *
  *    Puts data at the tail of the buffer. Returns pointer to the copied
- *    data area.  Returns NULL on error.
+ *    data area.  Returns NULL if the data is longer than the current tail
+ *    area.
  *
  * EXAMPLE
  *
@@ -779,12 +803,14 @@ unsigned char *silc_buffer_put_tail(SilcBuffer sb,
                                    const unsigned char *data,
                                    SilcUInt32 len)
 {
-#if defined(SILC_DEBUG)
+#ifdef SILC_DIST_INPLACE
   SILC_ASSERT(len <= silc_buffer_taillen(sb));
-#else
-  if (silc_unlikely(len > silc_buffer_taillen(sb)))
+#endif /* SILC_DIST_INPLACE */
+  if (silc_unlikely(len > silc_buffer_taillen(sb))) {
+    silc_set_errno(SILC_ERR_OVERFLOW);
     return NULL;
-#endif
+  }
+
   return (unsigned char *)memcpy(sb->tail, data, len);
 }
 
@@ -799,7 +825,7 @@ unsigned char *silc_buffer_put_tail(SilcBuffer sb,
  *
  *    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.  Returns NULL on error.
+ *    silc_buffer_pull_tail.  Returns NULL if system is out of memory.
  *
  ***/
 
@@ -824,7 +850,7 @@ SilcBuffer silc_buffer_alloc_size(SilcUInt32 len)
  *
  *    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.
+ *    silc_buffer_pull_tail.  Returns NULL if system is out of memory.
  *
  *    This routine use SilcStack are memory source.  If `stack' is NULL
  *    reverts back to normal allocating routine.
@@ -939,7 +965,7 @@ void silc_buffer_end(SilcBuffer sb)
  *
  *    Generates copy of a SilcBuffer. This copies everything inside the
  *    currently valid data area, nothing more. Use silc_buffer_clone to
- *    copy entire buffer.  Returns NULL on error.
+ *    copy entire buffer.  Returns NULL if system is out of memory.
  *
  ***/
 
@@ -967,7 +993,7 @@ SilcBuffer silc_buffer_copy(SilcBuffer sb)
  *
  *    Generates copy of a SilcBuffer. This copies everything inside the
  *    currently valid data area, nothing more. Use silc_buffer_clone to
- *    copy entire buffer.
+ *    copy entire buffer.  Returns NULL if system is out of memory.
  *
  *    This routine use SilcStack are memory source.  If `stack' is NULL
  *    reverts back to normal allocating routine.
@@ -1001,7 +1027,7 @@ SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb)
  *
  *    Clones SilcBuffer. This generates new SilcBuffer and copies
  *    everything from the source buffer. The result is exact clone of
- *    the original buffer.  Returns NULL on error.
+ *    the original buffer.  Returns NULL if system is out of memory.
  *
  ***/
 
@@ -1031,7 +1057,7 @@ SilcBuffer silc_buffer_clone(SilcBuffer sb)
  *
  *    Clones SilcBuffer. This generates new SilcBuffer and copies
  *    everything from the source buffer. The result is exact clone of
- *    the original buffer.
+ *    the original buffer.  Returns NULL if system is out of memory.
  *
  *    This routine use SilcStack are memory source.  If `stack' is NULL
  *    reverts back to normal allocating routine.
@@ -1068,7 +1094,7 @@ SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb)
  *    Reallocates buffer. Old data is saved into the new buffer. The buffer
  *    is exact clone of the old one except that there is now more space
  *    at the end of buffer.  This always returns the same `sb' unless `sb'
- *    was NULL. Returns NULL on error.
+ *    was NULL. Returns NULL if system is out of memory.
  *
  ***/
 
@@ -1109,7 +1135,7 @@ SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize)
  *
  *    Reallocates buffer. Old data is saved into the new buffer. The buffer
  *    is exact clone of the old one except that there is now more space
- *    at the end of buffer.
+ *    at the end of buffer.  Returns NULL if system is out of memory.
  *
  *    This routine use SilcStack are memory source.  If `stack' is NULL
  *    reverts back to normal allocating routine.
@@ -1167,7 +1193,7 @@ SilcBuffer silc_buffer_srealloc(SilcStack stack,
  *
  *    Same as silc_buffer_realloc but moves moves the tail area
  *    automatically so that the buffer is ready to use without calling the
- *    silc_buffer_pull_tail.  Returns NULL on error.
+ *    silc_buffer_pull_tail.  Returns NULL if system is out of memory.
  *
  ***/
 
@@ -1193,7 +1219,7 @@ SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize)
  *
  *    Same as silc_buffer_srealloc but moves moves the tail area
  *    automatically so that the buffer is ready to use without calling the
- *    silc_buffer_pull_tail.
+ *    silc_buffer_pull_tail.  Returns NULL if system is out of memory.
  *
  *    This routine use SilcStack are memory source.  If `stack' is NULL
  *    reverts back to normal allocating routine.
@@ -1229,7 +1255,7 @@ SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
  *    is at least the size of `size'.  If there is more space than `size'
  *    in the data area this does not do anything.  If there is enough
  *    space in the tail area this merely moves the tail area to reveal
- *    the extra space.  Returns FALSE on error.
+ *    the extra space.  Returns FALSE if system is out of memory.
  *
  ***/
 
@@ -1263,7 +1289,7 @@ SilcBool silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size)
  *    is at least the size of `size'.  If there is more space than `size'
  *    in the data area this does not do anything.  If there is enough
  *    space in the tail area this merely moves the tail area to reveal
- *    the extra space.  Returns FALSE on error.
+ *    the extra space.  Returns FALSE if system is out of memory.
  *
  *    This routine use SilcStack are memory source.  If `stack' is NULL
  *    reverts back to normal allocating routine.
@@ -1288,4 +1314,57 @@ SilcBool silc_buffer_senlarge(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
   return TRUE;
 }
 
+/****f* silcutil/SilcBufferAPI/silc_buffer_strchr
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_strchr(SilcBuffer sb, int c, SilcBool first);
+ *
+ * DESCRIPTION
+ *
+ *    Returns pointer to the occurence of the character `c' in the buffer
+ *    `sb'.  If the `first' is TRUE this finds the first occurene of `c',
+ *    if it is FALSE this finds the last occurence of `c'.  If the character
+ *    is found the `sb' data area is moved to that location and its pointer
+ *    is returned.  The silc_buffer_data call will return the same pointer.
+ *    Returns NULL if such character could not be located and the buffer
+ *    remains unmodified.
+ *
+ *    This call is equivalent to strchr(), strrchr(), memchr() and memrchr()
+ *    except it works with SilcBuffer.
+ *
+ * NOTES
+ *
+ *    This searches only the data area of the buffer.  Head and tail area
+ *    are not searched.
+ *
+ *    The `sb' data need not be NULL terminated.
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_strchr(SilcBuffer sb, int c, SilcBool first)
+{
+  int i;
+
+  if (first) {
+    for (i = 0; i < silc_buffer_len(sb); i++) {
+      if (sb->data[i] == (unsigned char)c) {
+       sb->data = &sb->data[i];
+       return sb->data;
+      }
+    }
+  } else {
+    for (i = silc_buffer_len(sb) - 1; 1 >= 0; i--) {
+      if (sb->data[i] == (unsigned char)c) {
+       sb->data = &sb->data[i];
+       return sb->data;
+      }
+    }
+  }
+
+  return NULL;
+}
+
 #endif /* SILCBUFFER_H */