Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1998 - 2006 Pekka Riikonen
+ Copyright (C) 1998 - 2007 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
*
* SOURCE
*/
-typedef struct {
+typedef struct SilcBufferObject {
unsigned char *head;
unsigned char *data;
unsigned char *tail;
/* Macros */
-/****d* silcutil/SilcBufferAPI/silc_buffer_truelen
+/****f* silcutil/SilcBufferAPI/silc_buffer_data
*
* NAME
*
- * SilcUInt32 silc_buffer_truelen(SilcBuffer sb)
+ * unsigned char *silc_buffer_data(SilcBuffer sb)
*
* DESCRIPTION
*
- * Returns the true length of the buffer.
+ * Returns pointer to the data area of the buffer.
*
* SOURCE
*/
-#define silc_buffer_truelen(x) (SilcUInt32)((x)->end - (x)->head)
+#define silc_buffer_data(x) (x)->data
/***/
-/****d* silcutil/SilcBufferAPI/silc_buffer_len
+/****f* silcutil/SilcBufferAPI/silc_buffer_datalen
*
* NAME
*
- * SilcUInt32 silc_buffer_len(SilcBuffer sb)
+ * #define silc_buffer_datalen ...
*
* DESCRIPTION
*
- * Returns the current length of the data area of the buffer.
+ * Macro that can be used in function argument list to give the data
+ * pointer and the data length, instead of calling both silc_buffer_data
+ * and silc_buffer_len separately.
+ *
+ * EXAMPLE
+ *
+ * // Following are the same thing
+ * silc_foo_function(foo, silc_buffer_datalen(buf));
+ * silc_foo_function(foo, silc_buffer_data(buf), silc_buffer_len(buf));
*
* SOURCE
*/
-#define silc_buffer_len(x) (SilcUInt32)((x)->tail - (x)->data)
+#define silc_buffer_datalen(x) (x) ? silc_buffer_data((x)) : NULL, \
+ (x) ? silc_buffer_len((x)) : 0
/***/
-/****d* silcutil/SilcBufferAPI/silc_buffer_headlen
+/* Inline functions */
+
+/****d* silcutil/SilcBufferAPI/silc_buffer_truelen
*
* NAME
*
- * SilcUInt32 silc_buffer_headlen(SilcBuffer sb)
+ * SilcUInt32 silc_buffer_truelen(SilcBuffer sb)
*
* DESCRIPTION
*
- * Returns the current length of the head data area of the buffer.
+ * Returns the true length of the buffer.
*
- * SOURCE
- */
-#define silc_buffer_headlen(x) (SilcUInt32)((x)->data - (x)->head)
-/***/
+ ***/
+static inline
+SilcUInt32 silc_buffer_truelen(SilcBuffer x)
+{
+ return (SilcUInt32)(x->end - x->head);
+}
-/****d* silcutil/SilcBufferAPI/silc_buffer_taillen
+/****d* silcutil/SilcBufferAPI/silc_buffer_len
*
* NAME
*
- * SilcUInt32 silc_buffer_taillen(SilcBuffer sb)
+ * SilcUInt32 silc_buffer_len(SilcBuffer sb)
*
* DESCRIPTION
*
- * Returns the current length of the tail data area of the buffer.
+ * Returns the current length of the data area of the buffer.
*
- * SOURCE
- */
-#define silc_buffer_taillen(x) (SilcUInt32)((x)->end - (x)->tail)
-/***/
+ ***/
+static inline
+SilcUInt32 silc_buffer_len(SilcBuffer x)
+{
+ return (SilcUInt32)(x->tail - x->data);
+}
-/****f* silcutil/SilcBufferAPI/silc_buffer_data
+/****d* silcutil/SilcBufferAPI/silc_buffer_headlen
*
* NAME
*
- * unsigned char *silc_buffer_data(SilcBuffer sb)
+ * SilcUInt32 silc_buffer_headlen(SilcBuffer sb)
*
* DESCRIPTION
*
- * Returns pointer to the data area of the buffer.
+ * Returns the current length of the head data area of the buffer.
*
- * SOURCE
- */
-#define silc_buffer_data(x) (x)->data
-/***/
+ ***/
+static inline
+SilcUInt32 silc_buffer_headlen(SilcBuffer x)
+{
+ return (SilcUInt32)(x->data - x->head);
+}
-/****f* silcutil/SilcBufferAPI/silc_buffer_datalen
+/****d* silcutil/SilcBufferAPI/silc_buffer_taillen
*
* NAME
*
- * #define silc_buffer_datalen ...
+ * SilcUInt32 silc_buffer_taillen(SilcBuffer sb)
*
* DESCRIPTION
*
- * Macro that can be used in function argument list to give the data
- * pointer and the data length, instead of calling both silc_buffer_data
- * and silc_buffer_len separately.
- *
- * EXAMPLE
- *
- * // Following are the same thing
- * silc_foo_function(foo, silc_buffer_datalen(buf));
- * silc_foo_function(foo, silc_buffer_data(buf), silc_buffer_len(buf));
+ * Returns the current length of the tail data area of the buffer.
*
- * SOURCE
- */
-#define silc_buffer_datalen(x) (x) ? silc_buffer_data((x)) : NULL, \
- (x) ? silc_buffer_len((x)) : 0
-/***/
-
-/* Inline functions */
+ ***/
+static inline
+SilcUInt32 silc_buffer_taillen(SilcBuffer x)
+{
+ return (SilcUInt32)(x->end - x->tail);
+}
/****f* silcutil/SilcBufferAPI/silc_buffer_alloc
*
/* Allocate new SilcBuffer */
sb = (SilcBuffer)silc_calloc(1, sizeof(*sb));
- if (!sb)
+ if (silc_unlikely(!sb))
return NULL;
- if (len) {
+ if (silc_likely(len)) {
/* Allocate the actual data area */
sb->head = (unsigned char *)silc_calloc(len, sizeof(*sb->head));
- if (!sb->head)
+ if (silc_unlikely(!sb->head))
return NULL;
/* Set pointers to the new buffer */
{
unsigned char *old_data = sb->data;
#if defined(SILC_DEBUG)
- assert(len <= silc_buffer_len(sb));
+ SILC_ASSERT(len <= silc_buffer_len(sb));
#else
- if (len > silc_buffer_len(sb))
+ if (silc_unlikely(len > silc_buffer_len(sb)))
return NULL;
#endif
sb->data += len;
{
unsigned char *old_data = sb->data;
#if defined(SILC_DEBUG)
- assert((sb->data - len) >= sb->head);
+ SILC_ASSERT((sb->data - len) >= sb->head);
#else
- if ((sb->data - len) < sb->head)
+ if (silc_unlikely((sb->data - len) < sb->head))
return NULL;
#endif
sb->data -= len;
{
unsigned char *old_tail = sb->tail;
#if defined(SILC_DEBUG)
- assert(len <= silc_buffer_taillen(sb));
+ SILC_ASSERT(len <= silc_buffer_taillen(sb));
#else
- if (len > silc_buffer_taillen(sb))
+ if (silc_unlikely(len > silc_buffer_taillen(sb)))
return NULL;
#endif
sb->tail += len;
{
unsigned char *old_tail = sb->tail;
#if defined(SILC_DEBUG)
- assert((sb->tail - len) >= sb->data);
+ SILC_ASSERT((sb->tail - len) >= sb->data);
#else
- if ((sb->tail - len) < sb->data)
+ if (silc_unlikely((sb->tail - len) < sb->data))
return NULL;
#endif
sb->tail -= len;
SilcUInt32 len)
{
#if defined(SILC_DEBUG)
- assert(len <= silc_buffer_headlen(sb));
+ SILC_ASSERT(len <= silc_buffer_headlen(sb));
#else
- if (len > silc_buffer_headlen(sb))
+ if (silc_unlikely(len > silc_buffer_headlen(sb)))
return NULL;
#endif
return (unsigned char *)memcpy(sb->head, data, len);
SilcUInt32 len)
{
#if defined(SILC_DEBUG)
- assert(len <= silc_buffer_len(sb));
+ SILC_ASSERT(len <= silc_buffer_len(sb));
#else
- if (len > silc_buffer_len(sb))
+ if (silc_unlikely(len > silc_buffer_len(sb)))
return NULL;
#endif
return (unsigned char *)memcpy(sb->data, data, len);
SilcUInt32 len)
{
#if defined(SILC_DEBUG)
- assert(len <= silc_buffer_taillen(sb));
+ SILC_ASSERT(len <= silc_buffer_taillen(sb));
#else
- if (len > silc_buffer_taillen(sb))
+ if (silc_unlikely(len > silc_buffer_taillen(sb)))
return NULL;
#endif
return (unsigned char *)memcpy(sb->tail, data, len);
SilcBuffer silc_buffer_alloc_size(SilcUInt32 len)
{
SilcBuffer sb = silc_buffer_alloc(len);
- if (!sb)
+ if (silc_unlikely(!sb))
return NULL;
silc_buffer_pull_tail(sb, len);
return sb;
silc_buffer_reset(sb);
}
+/****f* silcutil/SilcBufferAPI/silc_buffer_start
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * void silc_buffer_start(SilcBuffer sb);
+ *
+ * DESCRIPTION
+ *
+ * Moves the data area at the start of the buffer. The tail area remains
+ * as is.
+ *
+ ***/
+
+static inline
+void silc_buffer_start(SilcBuffer sb)
+{
+ sb->data = sb->head;
+}
+
+/****f* silcutil/SilcBufferAPI/silc_buffer_end
+ *
+ * SYNOPSIS
+ *
+ * static inline
+ * void silc_buffer_end(SilcBuffer sb);
+ *
+ * DESCRIPTION
+ *
+ * Moves the end of the data area to the end of the buffer. The start
+ * of the data area remains same. If the start of data area is at the
+ * start of the buffer, after this function returns the buffer's data
+ * area length is the length of the entire buffer.
+ *
+ ***/
+
+static inline
+void silc_buffer_end(SilcBuffer sb)
+{
+ sb->tail = sb->end;
+}
+
/****f* silcutil/SilcBufferAPI/silc_buffer_copy
*
* SYNOPSIS
SilcBuffer sb_new;
sb_new = silc_buffer_alloc_size(silc_buffer_len(sb));
- if (!sb_new)
+ if (silc_unlikely(!sb_new))
return NULL;
silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
SilcBuffer sb_new;
sb_new = silc_buffer_alloc_size(silc_buffer_truelen(sb));
- if (!sb_new)
+ if (silc_unlikely(!sb_new))
return NULL;
silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
sb_new->data = sb_new->head + silc_buffer_headlen(sb);
if (!sb)
return silc_buffer_alloc(newsize);
- if (newsize <= silc_buffer_truelen(sb))
+ if (silc_unlikely(newsize <= silc_buffer_truelen(sb)))
return sb;
hlen = silc_buffer_headlen(sb);
dlen = silc_buffer_len(sb);
h = (unsigned char *)silc_realloc(sb->head, newsize);
- if (!h)
+ if (silc_unlikely(!h))
return NULL;
sb->head = h;
sb->data = sb->head + hlen;
SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize)
{
sb = silc_buffer_realloc(sb, newsize);
- if (!sb)
+ 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 on error.
+ *
+ ***/
+
+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;
+}
+
/* SilcStack aware SilcBuffer routines */
/* Allocate new SilcBuffer */
sb = (SilcBuffer)silc_scalloc(stack, 1, sizeof(*sb));
- if (!sb)
+ if (silc_unlikely(!sb))
return NULL;
/* Allocate the actual data area */
sb->head = (unsigned char *)silc_smalloc_ua(stack, len);
- if (!sb->head)
+ if (silc_unlikely(!sb->head))
return NULL;
/* Set pointers to the new buffer */
SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len)
{
SilcBuffer sb = silc_buffer_salloc(stack, len);
- if (!sb)
+ if (silc_unlikely(!sb))
return NULL;
silc_buffer_pull_tail(sb, len);
return sb;
if (!h) {
/* Do slow and stack wasting realloc. The old sb->head is lost and
is freed eventually. */
- h = silc_smalloc_ua(stack, newsize);
- if (!h)
+ h = (unsigned char *)silc_smalloc_ua(stack, newsize);
+ if (silc_unlikely(!h))
return NULL;
memcpy(h, sb->head, silc_buffer_truelen(sb));
}
SilcBuffer sb, SilcUInt32 newsize)
{
sb = silc_buffer_srealloc(stack, sb, newsize);
- if (!sb)
+ if (silc_unlikely(!sb))
return NULL;
silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
return sb;
}
+/****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 on error.
+ *
+ * This routine use SilcStack are memory source. If `stack' is NULL
+ * reverts back to normal allocating routine.
+ *
+ ***/
+
+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_scopy
*
* SYNOPSIS
SilcBuffer sb_new;
sb_new = silc_buffer_salloc_size(stack, silc_buffer_len(sb));
- if (!sb_new)
+ if (silc_unlikely(!sb_new))
return NULL;
silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
SilcBuffer sb_new;
sb_new = silc_buffer_salloc_size(stack, silc_buffer_truelen(sb));
- if (!sb_new)
+ if (silc_unlikely(!sb_new))
return NULL;
silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
sb_new->data = sb_new->head + silc_buffer_headlen(sb);