X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcbuffer.h;h=9d35047082e03741eb6d0816f8a960f650b7c49f;hp=4dc1472ae6822fc5bff68575c5db519c7e0c3604;hb=0f0340b9fbce9704cc7171f8f0104ce9103d2de6;hpb=d60003d3019371d4ce834a6cbfbf41c257f5a5f7 diff --git a/lib/silcutil/silcbuffer.h b/lib/silcutil/silcbuffer.h index 4dc1472a..9d350470 100644 --- a/lib/silcutil/silcbuffer.h +++ b/lib/silcutil/silcbuffer.h @@ -1,10 +1,10 @@ /* - silcbuffer.h + silcbuffer.h Author: Pekka Riikonen - Copyright (C) 1998 - 2002 Pekka Riikonen + Copyright (C) 1998 - 2005 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 @@ -17,25 +17,21 @@ */ /* $Id$ */ -/* Optimized buffer managing routines. These are short inline functions. */ - -#ifndef SILCBUFFER_H -#define SILCBUFFER_H /****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. + * 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. * ***/ +#ifndef SILCBUFFER_H +#define SILCBUFFER_H + /****s* silcutil/SilcBufferAPI/SilcBuffer * * NAME @@ -49,20 +45,6 @@ * * 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 @@ -126,8 +108,6 @@ * SOURCE */ typedef struct { - SilcUInt32 truelen; - SilcUInt32 len; unsigned char *head; unsigned char *data; unsigned char *tail; @@ -137,20 +117,64 @@ typedef struct { /* Macros */ -/****d* silcutil/SilcBufferAPI/SILC_BUFFER_END - * +/****d* silcutil/SilcBufferAPI/silc_buffer_truelen + * + * NAME + * + * #define silc_buffer_truelen(buffer) + * + * DESCRIPTION + * + * Returns the true length of the buffer. + * + * SOURCE + */ +#define silc_buffer_truelen(x) (SilcUInt32)((x)->end - (x)->head) +/***/ + +/****d* silcutil/SilcBufferAPI/silc_buffer_len + * + * NAME + * + * #define silc_buffer_len(buffer) + * + * DESCRIPTION + * + * Returns the current length of the data area of the buffer. + * + * SOURCE + */ +#define silc_buffer_len(x) (SilcUInt32)((x)->tail - (x)->data) +/***/ + +/****d* silcutil/SilcBufferAPI/silc_buffer_headlen + * * NAME * - * #define SILC_BUFFER_END(...) + * #define silc_buffer_headlen(buffer) * * DESCRIPTION * - * Returns the true length of the buffer. This is used to pull - * the buffer area to the end of the buffer. + * Returns the current length of the head data area of the buffer. * * SOURCE */ -#define SILC_BUFFER_END(x) ((x)->end - (x)->head) +#define silc_buffer_headlen(x) (SilcUInt32)((x)->data - (x)->head) +/***/ + +/****d* silcutil/SilcBufferAPI/silc_buffer_taillen + * + * NAME + * + * #define silc_buffer_taillen(buffer) + * + * DESCRIPTION + * + * Returns the current length of the tail data area of the buffer. + * + * SOURCE + */ +#define silc_buffer_taillen(x) (SilcUInt32)((x)->end - (x)->tail) /***/ /* Inline functions */ @@ -164,10 +188,10 @@ typedef struct { * * DESCRIPTION * - * Allocates new SilcBuffer and returns it. + * Allocates new SilcBuffer and returns it. Returns NULL on error. * ***/ - + static inline SilcBuffer silc_buffer_alloc(SilcUInt32 len) { @@ -184,10 +208,9 @@ SilcBuffer silc_buffer_alloc(SilcUInt32 len) return NULL; /* Set pointers to the new buffer */ - sb->truelen = len; sb->data = sb->head; sb->tail = sb->head; - sb->end = sb->head + sb->truelen; + sb->end = sb->head + len; return sb; } @@ -211,7 +234,7 @@ void silc_buffer_free(SilcBuffer sb) if (sb) { #if defined(SILC_DEBUG) if (sb->head) - memset(sb->head, 'F', sb->truelen); + memset(sb->head, 'F', silc_buffer_truelen(sb)); #endif silc_free(sb->head); silc_free(sb); @@ -241,9 +264,8 @@ unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len) { unsigned char *buf = sb->head; if (data_len) - *data_len = sb->truelen; + *data_len = silc_buffer_truelen(sb); sb->head = sb->data = sb->tail = sb->end = NULL; - sb->len = sb->truelen = 0; return buf; } @@ -263,6 +285,11 @@ unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len) * can be used to set the data to static buffer without needing any * memory allocations. The `data' will not be copied to the buffer. * + * EXAMPLE + * + * SilcBufferStruct buf; + * silc_buffer_set(&buf, data, data_len); + * ***/ static inline @@ -270,7 +297,6 @@ 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; } /****f* silcutil/SilcBufferAPI/silc_buffer_pull @@ -284,7 +310,7 @@ 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. + * area before pulling. Returns NULL on error. * * EXAMPLE * @@ -298,20 +324,22 @@ void silc_buffer_set(SilcBuffer sb, unsigned char *data, SilcUInt32 data_len) * | head | data | tail | * --------------------------------- * ^ + * + * silc_buffer_pull(sb, 20); + * ***/ static inline unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len) { unsigned char *old_data = sb->data; - #if defined(SILC_DEBUG) - assert(len <= (SilcUInt32)(sb->tail - sb->data)); + assert(len <= silc_buffer_len(sb)); +#else + if (len > silc_buffer_len(sb)) + return NULL; #endif - sb->data += len; - sb->len -= len; - return old_data; } @@ -325,8 +353,8 @@ unsigned char *silc_buffer_pull(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. + * valid data area is also incremented. Returns a pointer to the + * data area before pushing. Returns NULL on error. * * EXAMPLE * @@ -341,20 +369,21 @@ unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len) * --------------------------------- * ^ * + * silc_buffer_push(sb, 20); + * ***/ static inline unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len) { unsigned char *old_data = sb->data; - #if defined(SILC_DEBUG) assert((sb->data - len) >= sb->head); +#else + if ((sb->data - len) < sb->head) + return NULL; #endif - sb->data -= len; - sb->len += len; - return old_data; } @@ -362,14 +391,14 @@ unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len) * * SYNOPSIS * - * static inline + * 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. + * data area is also incremented. Returns a pointer to the data area + * before pulling. Returns NULL on error. * * EXAMPLE * @@ -384,20 +413,21 @@ unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len) * --------------------------------- * ^ * + * silc_buffer_pull_tail(sb, 23); + * ***/ static inline unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len) { unsigned char *old_tail = sb->tail; - #if defined(SILC_DEBUG) - assert((SilcUInt32)(sb->end - sb->tail) >= len); + assert(len <= silc_buffer_taillen(sb)); +#else + if (len > silc_buffer_taillen(sb)) + return NULL; #endif - sb->tail += len; - sb->len += len; - return old_tail; } @@ -412,7 +442,7 @@ 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. + * tail section before pushing. Returns NULL on error. * * EXAMPLE * @@ -427,20 +457,21 @@ unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len) * --------------------------------- * ^ * + * silc_buffer_push_tail(sb, 23); + * ***/ static inline unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len) { unsigned char *old_tail = sb->tail; - #if defined(SILC_DEBUG) assert((sb->tail - len) >= sb->data); +#else + if ((sb->tail - len) < sb->data) + return NULL; #endif - sb->tail -= len; - sb->len -= len; - return old_tail; } @@ -449,14 +480,14 @@ unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len) * SYNOPSIS * * static inline - * unsigned char *silc_buffer_put_head(SilcBuffer sb, + * 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. + * data area. Returns NULL on error. * * EXAMPLE * @@ -464,7 +495,9 @@ unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len) * | head | data | tail | * --------------------------------- * ^ - * Puts data to the head section. + * Puts data to the head section. + * + * silc_buffer_put_head(sb, data, data_len); * ***/ @@ -474,7 +507,10 @@ unsigned char *silc_buffer_put_head(SilcBuffer sb, SilcUInt32 len) { #if defined(SILC_DEBUG) - assert((SilcUInt32)(sb->data - sb->head) >= len); + assert(len <= silc_buffer_headlen(sb)); +#else + if (len > silc_buffer_headlen(sb)) + return NULL; #endif return (unsigned char *)memcpy(sb->head, data, len); } @@ -491,7 +527,7 @@ 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. + * to the copied data area. Returns NULL on error. * * EXAMPLE * @@ -501,6 +537,8 @@ unsigned char *silc_buffer_put_head(SilcBuffer sb, * ^ * Puts data to the data section. * + * silc_buffer_put(sb, data, data_len); + * ***/ static inline @@ -509,7 +547,10 @@ unsigned char *silc_buffer_put(SilcBuffer sb, SilcUInt32 len) { #if defined(SILC_DEBUG) - assert((SilcUInt32)(sb->tail - sb->data) >= len); + assert(len <= silc_buffer_len(sb)); +#else + if (len > silc_buffer_len(sb)) + return NULL; #endif return (unsigned char *)memcpy(sb->data, data, len); } @@ -526,7 +567,7 @@ unsigned char *silc_buffer_put(SilcBuffer sb, * DESCRIPTION * * Puts data at the tail of the buffer. Returns pointer to the copied - * data area. + * data area. Returns NULL on error. * * EXAMPLE * @@ -536,6 +577,8 @@ unsigned char *silc_buffer_put(SilcBuffer sb, * ^ * Puts data to the tail section. * + * silc_buffer_put_tail(sb, data, data_len); + * ***/ static inline @@ -544,7 +587,10 @@ unsigned char *silc_buffer_put_tail(SilcBuffer sb, SilcUInt32 len) { #if defined(SILC_DEBUG) - assert((SilcUInt32)(sb->end - sb->tail) >= len); + assert(len <= silc_buffer_taillen(sb)); +#else + if (len > silc_buffer_taillen(sb)) + return NULL; #endif return (unsigned char *)memcpy(sb->tail, data, len); } @@ -560,7 +606,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. + * silc_buffer_pull_tail. Returns NULL on error. * ***/ @@ -574,6 +620,27 @@ SilcBuffer silc_buffer_alloc_size(SilcUInt32 len) return sb; } +/****f* silcutil/SilcBufferAPI/silc_buffer_reset + * + * SYNOPSIS + * + * static inline + * void silc_buffer_reset(SilcBuffer sb); + * + * DESCRIPTION + * + * Resets the buffer to the state as if it was just allocated by + * silc_buffer_alloc. This does not clear the data area. Use + * silc_buffer_clear if you also want to clear the data area. + * + ***/ + +static inline +void silc_buffer_reset(SilcBuffer sb) +{ + sb->data = sb->tail = sb->head; +} + /****f* silcutil/SilcBufferAPI/silc_buffer_clear * * SYNOPSIS @@ -591,12 +658,8 @@ SilcBuffer silc_buffer_alloc_size(SilcUInt32 len) 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; + memset(sb->head, 0, silc_buffer_truelen(sb)); + silc_buffer_reset(sb); } /****f* silcutil/SilcBufferAPI/silc_buffer_copy @@ -610,7 +673,7 @@ void silc_buffer_clear(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 on error. * ***/ @@ -619,10 +682,10 @@ SilcBuffer silc_buffer_copy(SilcBuffer sb) { SilcBuffer sb_new; - sb_new = silc_buffer_alloc_size(sb->len); + sb_new = silc_buffer_alloc_size(silc_buffer_len(sb)); if (!sb_new) return NULL; - silc_buffer_put(sb_new, sb->data, sb->len); + silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb)); return sb_new; } @@ -638,7 +701,7 @@ SilcBuffer silc_buffer_copy(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 on error. * ***/ @@ -647,13 +710,12 @@ SilcBuffer silc_buffer_clone(SilcBuffer sb) { SilcBuffer sb_new; - sb_new = silc_buffer_alloc_size(sb->truelen); + sb_new = silc_buffer_alloc_size(silc_buffer_truelen(sb)); 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_put(sb_new, sb->head, silc_buffer_truelen(sb)); + sb_new->data = sb_new->head + silc_buffer_headlen(sb); + sb_new->tail = sb_new->data + silc_buffer_len(sb); return sb_new; } @@ -667,34 +729,272 @@ SilcBuffer silc_buffer_clone(SilcBuffer sb) * * 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. + * 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. * ***/ static inline SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize) { - SilcBuffer sb_new; + SilcUInt32 hlen, dlen; + unsigned char *h; if (!sb) return silc_buffer_alloc(newsize); - if (newsize <= sb->truelen) + if (newsize <= silc_buffer_truelen(sb)) return sb; - sb_new = silc_buffer_alloc_size(newsize); + hlen = silc_buffer_headlen(sb); + dlen = silc_buffer_len(sb); + h = (unsigned char *)silc_realloc(sb->head, newsize); + if (!h) + return NULL; + sb->head = h; + sb->data = sb->head + hlen; + sb->tail = sb->data + dlen; + sb->end = sb->head + newsize; + + return sb; +} + +/****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 on error. + * + ***/ + +static inline +SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize) +{ + sb = silc_buffer_realloc(sb, newsize); + if (!sb) + return NULL; + silc_buffer_pull_tail(sb, silc_buffer_taillen(sb)); + return sb; +} + + +/* SilcStack aware SilcBuffer routines */ + +/****f* silcutil/SilcBufferAPI/silc_buffer_salloc + * + * SYNOPSIS + * + * static inline + * SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len); + * + * DESCRIPTION + * + * Allocates new SilcBuffer and returns it. + * + * This routine use SilcStack are memory source. + * + ***/ + +static inline +SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len) +{ + SilcBuffer sb; + + /* Allocate new SilcBuffer */ + sb = (SilcBuffer)silc_scalloc(stack, 1, sizeof(*sb)); + if (!sb) + return NULL; + + /* Allocate the actual data area */ + sb->head = (unsigned char *)silc_smalloc_ua(stack, len); + if (!sb->head) + return NULL; + + /* Set pointers to the new buffer */ + sb->data = sb->head; + sb->tail = sb->head; + sb->end = sb->head + len; + + return sb; +} + +/****f* silcutil/SilcBufferAPI/silc_buffer_salloc_size + * + * SYNOPSIS + * + * static inline + * SilcBuffer silc_buffer_salloc_size(SilcStack stack, 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. + * + * This routine use SilcStack are memory source. + * + ***/ + +static inline +SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len) +{ + SilcBuffer sb = silc_buffer_salloc(stack, len); + if (!sb) + return NULL; + silc_buffer_pull_tail(sb, len); + return sb; +} + +/****f* silcutil/SilcBufferAPI/silc_buffer_srealloc + * + * SYNOPSIS + * + * static inline + * SilcBuffer silc_buffer_srealloc(SilcStack stack, + * SilcBuffer sb, SilcUInt32 newsize); + * + * DESCRIPTION + * + * 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 routine use SilcStack are memory source. + * + ***/ + +static inline +SilcBuffer silc_buffer_srealloc(SilcStack stack, + SilcBuffer sb, SilcUInt32 newsize) +{ + SilcUInt32 hlen, dlen; + unsigned char *h; + + if (!sb) + return silc_buffer_salloc(stack, newsize); + + if (newsize <= silc_buffer_truelen(sb)) + return sb; + + hlen = silc_buffer_headlen(sb); + dlen = silc_buffer_len(sb); + h = (unsigned char *)silc_srealloc_ua(stack, silc_buffer_truelen(sb), + sb->head, newsize); + 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) + return NULL; + memcpy(h, sb->head, silc_buffer_truelen(sb)); + } + + sb->head = h; + sb->data = sb->head + hlen; + sb->tail = sb->data + dlen; + sb->end = sb->head + newsize; + + 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. + * + * This routine use SilcStack are memory source. + * + ***/ + +static inline +SilcBuffer silc_buffer_srealloc_size(SilcStack stack, + SilcBuffer sb, SilcUInt32 newsize) +{ + sb = silc_buffer_srealloc(stack, sb, newsize); + if (!sb) + return NULL; + silc_buffer_pull_tail(sb, silc_buffer_taillen(sb)); + return sb; +} + +/****f* silcutil/SilcBufferAPI/silc_buffer_scopy + * + * SYNOPSIS + * + * static inline + * SilcBuffer silc_buffer_scopy(SilcStack stack, 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. + * + * This routine use SilcStack are memory source. + * + ***/ + +static inline +SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb) +{ + SilcBuffer sb_new; + + sb_new = silc_buffer_salloc_size(stack, silc_buffer_len(sb)); 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_put(sb_new, sb->data, silc_buffer_len(sb)); + + return sb_new; +} + +/****f* silcutil/SilcBufferAPI/silc_buffer_sclone + * + * SYNOPSIS + * + * static inline + * SilcBuffer silc_buffer_sclone(SilcStack stack, 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. + * + * This routine use SilcStack are memory source. + * + ***/ + +static inline +SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb) +{ + SilcBuffer sb_new; - silc_buffer_free(sb); + sb_new = silc_buffer_salloc_size(stack, silc_buffer_truelen(sb)); + if (!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); + sb_new->tail = sb_new->data + silc_buffer_len(sb); return sb_new; } -#endif +#endif /* SILCBUFFER_H */