+/****f* silcutil/SilcBufferAPI/silc_buffer_realloc_size
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize);
+ *
+ * DESCRIPTION
+ *
+ * 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 if system is out of memory.
+ *
+ ***/
+
+static inline
+SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize)
+{
+ sb = silc_buffer_realloc(sb, newsize);
+ if (silc_unlikely(!sb))
+ return NULL;
+ silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
+ return sb;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_srealloc_size
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
+ * SilcBuffer sb, SilcUInt32 newsize);
+ *
+ * DESCRIPTION
+ *
+ * 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. 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.
+ *
+ * Note that this call consumes the `stack'. The caller should push the
+ * stack before calling the function and pop it later.
+ *
+ ***/
+
+static inline
+SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
+ SilcBuffer sb, SilcUInt32 newsize)
+{
+ sb = silc_buffer_srealloc(stack, sb, newsize);
+ if (silc_unlikely(!sb))
+ return NULL;
+ silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
+ return sb;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_enlarge
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBuffer silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size);
+ *
+ * DESCRIPTION
+ *
+ * Enlarges the buffer by the amount of `size' if it doesn't have that
+ * must space in the data area and in the tail area. Moves the tail
+ * area automatically after enlarging so that the current data area
+ * 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 if system is out of memory.
+ *
+ ***/
+
+static inline
+SilcBool silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size)
+{
+ if (size > silc_buffer_len(sb)) {
+ if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
+ if (silc_unlikely(!silc_buffer_realloc(sb, silc_buffer_truelen(sb) +
+ (size - silc_buffer_taillen(sb) -
+ silc_buffer_len(sb)))))
+ return FALSE;
+ silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
+ }
+ return TRUE;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_senlarge
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBuffer silc_buffer_senlarge(SilcStack stack, SilcBuffer sb,
+ * SilcUInt32 size);
+ *
+ * DESCRIPTION
+ *
+ * Enlarges the buffer by the amount of `size' if it doesn't have that
+ * must space in the data area and in the tail area. Moves the tail
+ * area automatically after enlarging so that the current data area
+ * 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 if system is out of memory.
+ *
+ * This routine use SilcStack are memory source. If `stack' is NULL
+ * reverts back to normal allocating routine.
+ *
+ * Note that this call consumes the `stack'. The caller should push the
+ * stack before calling the function and pop it later.
+ *
+ ***/
+
+static inline
+SilcBool silc_buffer_senlarge(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
+{
+ if (size > silc_buffer_len(sb)) {
+ if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
+ if (silc_unlikely(!silc_buffer_srealloc(stack, sb,
+ silc_buffer_truelen(sb) +
+ (size - silc_buffer_taillen(sb) -
+ silc_buffer_len(sb)))))
+ return FALSE;
+ silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
+ }
+ return TRUE;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_append
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBuffer silc_buffer_append(SilcBuffer sb, SilcUInt32 size);
+ *
+ * DESCRIPTION
+ *
+ * Appends the current data area by the amount of `size'. The tail area
+ * of the buffer remains intact and contains the same data than the old
+ * tail area (the data is copied to the new tail area). After appending
+ * there is now `size' bytes more free area in the data area. Returns
+ * FALSE if system is out of memory.
+ *
+ * EXAMPLE
+ *
+ * Before appending:
+ * ---------------------------------
+ * | head | data | tail |
+ * ---------------------------------
+ *
+ * After appending:
+ * ------------------------------------
+ * | head | data | tail |
+ * -------------------------------------
+ *
+ * silc_buffer_append(sb, 5);
+ *
+ ***/
+
+static inline
+SilcBool silc_buffer_append(SilcBuffer sb, SilcUInt32 size)
+{
+ if (silc_unlikely(!silc_buffer_realloc(sb, silc_buffer_truelen(sb) + size)))
+ return FALSE;
+
+ /* Enlarge data area */
+ silc_buffer_pull_tail(sb, size);
+
+ /* Copy old tail area to new tail area */
+ silc_buffer_put_tail(sb, sb->tail - size, silc_buffer_taillen(sb));
+
+ return TRUE;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_append
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBool silc_buffer_sappend(SilcStack stack, SilcBuffer sb,
+ * SilcUInt32 size)
+ *
+ * DESCRIPTION
+ *
+ * Appends the current data area by the amount of `size'. The tail area
+ * of the buffer remains intact and contains the same data than the old
+ * tail area (the data is copied to the new tail area). After appending
+ * there is now `size' bytes more free area in the data area. 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.
+ *
+ * Note that this call consumes the `stack'. The caller should push the
+ * stack before calling the function and pop it later.
+ *
+ * EXAMPLE
+ *
+ * Before appending:
+ * ---------------------------------
+ * | head | data | tail |
+ * ---------------------------------
+ *
+ * After appending:
+ * ------------------------------------
+ * | head | data | tail |
+ * -------------------------------------
+ *
+ * silc_buffer_append(sb, 5);
+ *
+ ***/
+
+static inline
+SilcBool silc_buffer_sappend(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
+{
+ if (silc_unlikely(!silc_buffer_srealloc(stack, sb,
+ silc_buffer_truelen(sb) + size)))
+ return FALSE;
+
+ /* Enlarge data area */
+ silc_buffer_pull_tail(sb, size);
+
+ /* Copy old tail area to new tail area */
+ silc_buffer_put_tail(sb, sb->tail - size, silc_buffer_taillen(sb));
+
+ 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;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_equal
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBool silc_buffer_equal(SilcBuffer sb1, SilcBuffer sb2)
+ *
+ * DESCRIPTION
+ *
+ * Compares if the data area of the buffer `sb1' and `sb2' are identical.
+ * Returns TRUE if they match and FALSE if they differ.
+ *
+ ***/
+
+static inline
+SilcBool silc_buffer_equal(SilcBuffer sb1, SilcBuffer sb2)
+{
+ if (silc_buffer_len(sb1) != silc_buffer_len(sb2))
+ return FALSE;
+ return memcmp(sb1->data, sb2->data, silc_buffer_len(sb1)) == 0;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_memcmp
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * SilcBool silc_buffer_memcmp(SilcBuffer buffer,
+ * const unsigned char *data,
+ * SilcUInt32 data_len)
+ *
+ * DESCRIPTION
+ *
+ * Compares the data area of the buffer with the `data'. Returns TRUE
+ * if the data area is identical to `data' or FALSE if they differ.
+ *
+ ***/
+
+static inline
+SilcBool silc_buffer_memcmp(SilcBuffer buffer, const unsigned char *data,
+ SilcUInt32 data_len)
+{
+ if (silc_buffer_len(buffer) != data_len)
+ return FALSE;
+ return memcmp(buffer->data, data, data_len) == 0;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_printf
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * void silc_buffer_printf(SilcBuffer sb, SilcBool newline);
+ *
+ * DESCRIPTION
+ *
+ * Prints the current data area of `sb' into stdout. If `newline' is
+ * TRUE prints '\n' after the data in the buffer.
+ *
+ ***/
+
+static inline
+void silc_buffer_printf(SilcBuffer sb, SilcBool newline)
+{
+ silc_file_write(1, silc_buffer_data(sb), silc_buffer_len(sb));
+ if (newline)
+ printf("\n");
+ fflush(stdout);
+}
+
+#endif /* SILCBUFFER_H */