5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1998 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 /****h* silcutil/SILC Buffer Interface
25 * SilcBuffer is very simple and easy to use, yet you can do to the
26 * buffer almost anything you want with its method functions. The buffer
27 * is constructed of four different data sections that in whole creates
28 * the allocated data area.
35 /****s* silcutil/SilcBufferAPI/SilcBuffer
39 * typedef struct { ... } *SilcBuffer, SilcBufferStruct;
43 * SILC Buffer object. Following short description of the fields
50 * Head of the allocated buffer. This is the start of the allocated
51 * data area and remains as same throughout the lifetime of the buffer.
52 * However, the end of the head area or the start of the currently valid
53 * data area is variable.
55 * --------------------------------
56 * | head | data | tail |
57 * --------------------------------
60 * Current head section in the buffer is sb->data - sb->head.
62 * unsigned char *data;
64 * Currently valid data area. This is the start of the currently valid
65 * main data area. The data area is variable in all directions.
67 * --------------------------------
68 * | head | data | tail |
69 * --------------------------------
72 * Current valid data area in the buffer is sb->tail - sb->data.
74 * unsigned char *tail;
76 * Tail of the buffer. This is the end of the currently valid data area
77 * or start of the tail area. The start of the tail area is variable.
79 * --------------------------------
80 * | head | data | tail |
81 * --------------------------------
84 * Current tail section in the buffer is sb->end - sb->tail.
88 * End of the allocated buffer. This is the end of the allocated data
89 * area and remains as same throughout the lifetime of the buffer.
90 * Usually this field is not needed except when checking the size
93 * --------------------------------
94 * | head | data | tail |
95 * --------------------------------
98 * Length of the entire buffer is (ie. truelen) sb->end - sb->head.
100 * Currently valid data area is considered to be the main data area in
101 * the buffer. However, the entire buffer is of course valid data and can
102 * be used as such. Usually head section of the buffer includes different
103 * kind of headers or similar. Data section includes the main data of
104 * the buffer. Tail section can be seen as a reserve space of the data
105 * section. Tail section can be pulled towards end, and thus the data
106 * section becomes larger.
108 * SILC Buffer is not thread-safe. If the same SilcBuffer context must be
109 * used in multithreaded environment concurrency control must be employed.
113 typedef struct SilcBufferObject {
118 } *SilcBuffer, SilcBufferStruct;
123 /****f* silcutil/SilcBufferAPI/silc_buffer_data
127 * unsigned char *silc_buffer_data(SilcBuffer sb)
131 * Returns pointer to the data area of the buffer.
135 #define silc_buffer_data(x) (x)->data
138 /****f* silcutil/SilcBufferAPI/silc_buffer_datalen
142 * #define silc_buffer_datalen ...
146 * Macro that can be used in function argument list to give the data
147 * pointer and the data length, instead of calling both silc_buffer_data
148 * and silc_buffer_len separately.
152 * // Following are the same thing
153 * silc_foo_function(foo, silc_buffer_datalen(buf));
154 * silc_foo_function(foo, silc_buffer_data(buf), silc_buffer_len(buf));
158 #define silc_buffer_datalen(x) (x) ? silc_buffer_data((x)) : NULL, \
159 (x) ? silc_buffer_len((x)) : 0
162 /* Inline functions */
164 /****d* silcutil/SilcBufferAPI/silc_buffer_truelen
168 * SilcUInt32 silc_buffer_truelen(SilcBuffer sb)
172 * Returns the true length of the buffer.
176 SilcUInt32 silc_buffer_truelen(SilcBuffer x)
178 return (SilcUInt32)(x->end - x->head);
181 /****d* silcutil/SilcBufferAPI/silc_buffer_len
185 * SilcUInt32 silc_buffer_len(SilcBuffer sb)
189 * Returns the current length of the data area of the buffer.
193 SilcUInt32 silc_buffer_len(SilcBuffer x)
195 return (SilcUInt32)(x->tail - x->data);
198 /****d* silcutil/SilcBufferAPI/silc_buffer_headlen
202 * SilcUInt32 silc_buffer_headlen(SilcBuffer sb)
206 * Returns the current length of the head data area of the buffer.
210 SilcUInt32 silc_buffer_headlen(SilcBuffer x)
212 return (SilcUInt32)(x->data - x->head);
215 /****d* silcutil/SilcBufferAPI/silc_buffer_taillen
219 * SilcUInt32 silc_buffer_taillen(SilcBuffer sb)
223 * Returns the current length of the tail data area of the buffer.
227 SilcUInt32 silc_buffer_taillen(SilcBuffer x)
229 return (SilcUInt32)(x->end - x->tail);
232 /****f* silcutil/SilcBufferAPI/silc_buffer_alloc
237 * SilcBuffer silc_buffer_alloc(SilcUInt32 len);
241 * Allocates new SilcBuffer and returns it. Returns NULL on error.
246 SilcBuffer silc_buffer_alloc(SilcUInt32 len)
250 /* Allocate new SilcBuffer */
251 sb = (SilcBuffer)silc_calloc(1, sizeof(*sb));
252 if (silc_unlikely(!sb))
255 if (silc_likely(len)) {
256 /* Allocate the actual data area */
257 sb->head = (unsigned char *)silc_calloc(len, sizeof(*sb->head));
258 if (silc_unlikely(!sb->head))
261 /* Set pointers to the new buffer */
264 sb->end = sb->head + len;
270 /****f* silcutil/SilcBufferAPI/silc_buffer_free
275 * void silc_buffer_free(SilcBuffer sb);
279 * Frees SilcBuffer. Can be called safely `sb' as NULL.
283 * Must not be called for buffers allocated with silc_buffer_salloc,
284 * silc_buffer_salloc_size, silc_buffer_scopy and silc_buffer_sclone.
289 void silc_buffer_free(SilcBuffer sb)
292 #if defined(SILC_DEBUG)
294 memset(sb->head, 'F', silc_buffer_truelen(sb));
301 /****f* silcutil/SilcBufferAPI/silc_buffer_steal
306 * unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len);
310 * Steals the data from the buffer `sb'. This returns pointer to the
311 * start of the buffer and the true length of that buffer. The `sb'
312 * cannot be used anymore after calling this function because the
313 * data buffer was stolen. The `sb' must be freed with silc_buffer_free.
314 * The caller is responsible of freeing the stolen data buffer with
320 unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
322 unsigned char *buf = sb->head;
324 *data_len = silc_buffer_truelen(sb);
325 sb->head = sb->data = sb->tail = sb->end = NULL;
329 /****f* silcutil/SilcBufferAPI/silc_buffer_purge
334 * void silc_buffer_purge(SilcBuffer sb);
338 * Same as silc_buffer_free but free's only the contents of the buffer
339 * not the buffer itself. The `sb' remains intact, data is freed. Buffer
340 * is ready for re-use after calling this function.
344 * Must not be called for buffers allocated with silc_buffer_salloc,
345 * silc_buffer_salloc_size, silc_buffer_scopy and silc_buffer_sclone.
350 void silc_buffer_purge(SilcBuffer sb)
352 silc_free(silc_buffer_steal(sb, NULL));
355 /****f* silcutil/SilcBufferAPI/silc_buffer_set
360 * void silc_buffer_set(SilcBuffer sb,
361 * unsigned char *data,
362 * SilcUInt32 data_len);
366 * Sets the `data' and `data_len' to the buffer pointer sent as argument.
367 * The data area is automatically set to the `data_len'. This function
368 * can be used to set the data to static buffer without needing any
369 * memory allocations. The `data' will not be copied to the buffer.
373 * SilcBufferStruct buf;
374 * silc_buffer_set(&buf, data, data_len);
379 void silc_buffer_set(SilcBuffer sb, unsigned char *data, SilcUInt32 data_len)
381 sb->data = sb->head = data;
382 sb->tail = sb->end = data + data_len;
385 /****f* silcutil/SilcBufferAPI/silc_buffer_pull
390 * unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len);
394 * Pulls current data area towards end. The length of the currently
395 * valid data area is also decremented. Returns pointer to the data
396 * area before pulling. Returns NULL on error.
400 * ---------------------------------
401 * | head | data | tail |
402 * ---------------------------------
404 * Pulls the start of the data area.
406 * ---------------------------------
407 * | head | data | tail |
408 * ---------------------------------
411 * silc_buffer_pull(sb, 20);
416 unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len)
418 unsigned char *old_data = sb->data;
419 #if defined(SILC_DEBUG)
420 SILC_ASSERT(len <= silc_buffer_len(sb));
422 if (silc_unlikely(len > silc_buffer_len(sb)))
429 /****f* silcutil/SilcBufferAPI/silc_buffer_push
434 * unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len);
438 * Pushes current data area towards beginning. Length of the currently
439 * valid data area is also incremented. Returns a pointer to the
440 * data area before pushing. Returns NULL on error.
444 * ---------------------------------
445 * | head | data | tail |
446 * ---------------------------------
448 * Pushes the start of the data area.
450 * ---------------------------------
451 * | head | data | tail |
452 * ---------------------------------
455 * silc_buffer_push(sb, 20);
460 unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len)
462 unsigned char *old_data = sb->data;
463 #if defined(SILC_DEBUG)
464 SILC_ASSERT((sb->data - len) >= sb->head);
466 if (silc_unlikely((sb->data - len) < sb->head))
473 /****f* silcutil/SilcBufferAPI/silc_buffer_pull_tail
478 * unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len);
482 * Pulls current tail section towards end. Length of the current valid
483 * data area is also incremented. Returns a pointer to the data area
484 * before pulling. Returns NULL on error.
488 * ---------------------------------
489 * | head | data | tail |
490 * ---------------------------------
492 * Pulls the start of the tail section.
494 * ---------------------------------
495 * | head | data | tail |
496 * ---------------------------------
499 * silc_buffer_pull_tail(sb, 23);
504 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len)
506 unsigned char *old_tail = sb->tail;
507 #if defined(SILC_DEBUG)
508 SILC_ASSERT(len <= silc_buffer_taillen(sb));
510 if (silc_unlikely(len > silc_buffer_taillen(sb)))
517 /****f* silcutil/SilcBufferAPI/silc_buffer_push_tail
522 * unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len);
526 * Pushes current tail section towards beginning. Length of the current
527 * valid data area is also decremented. Returns a pointer to the
528 * tail section before pushing. Returns NULL on error.
532 * ---------------------------------
533 * | head | data | tail |
534 * ---------------------------------
536 * Pushes the start of the tail section.
538 * ---------------------------------
539 * | head | data | tail |
540 * ---------------------------------
543 * silc_buffer_push_tail(sb, 23);
548 unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len)
550 unsigned char *old_tail = sb->tail;
551 #if defined(SILC_DEBUG)
552 SILC_ASSERT((sb->tail - len) >= sb->data);
554 if (silc_unlikely((sb->tail - len) < sb->data))
561 /****f* silcutil/SilcBufferAPI/silc_buffer_put_head
566 * unsigned char *silc_buffer_put_head(SilcBuffer sb,
567 * const unsigned char *data,
572 * Puts data at the head of the buffer. Returns pointer to the copied
573 * data area. Returns NULL on error.
577 * ---------------------------------
578 * | head | data | tail |
579 * ---------------------------------
581 * Puts data to the head section.
583 * silc_buffer_put_head(sb, data, data_len);
588 unsigned char *silc_buffer_put_head(SilcBuffer sb,
589 const unsigned char *data,
592 #if defined(SILC_DEBUG)
593 SILC_ASSERT(len <= silc_buffer_headlen(sb));
595 if (silc_unlikely(len > silc_buffer_headlen(sb)))
598 return (unsigned char *)memcpy(sb->head, data, len);
601 /****f* silcutil/SilcBufferAPI/silc_buffer_put
606 * unsigned char *silc_buffer_put(SilcBuffer sb,
607 * const unsigned char *data,
612 * Puts data at the start of the valid data area. Returns a pointer
613 * to the copied data area. Returns NULL on error.
617 * ---------------------------------
618 * | head | data | tail |
619 * ---------------------------------
621 * Puts data to the data section.
623 * silc_buffer_put(sb, data, data_len);
628 unsigned char *silc_buffer_put(SilcBuffer sb,
629 const unsigned char *data,
632 #if defined(SILC_DEBUG)
633 SILC_ASSERT(len <= silc_buffer_len(sb));
635 if (silc_unlikely(len > silc_buffer_len(sb)))
638 return (unsigned char *)memcpy(sb->data, data, len);
641 /****f* silcutil/SilcBufferAPI/silc_buffer_put_tail
646 * unsigned char *silc_buffer_put_tail(SilcBuffer sb,
647 * const unsigned char *data,
652 * Puts data at the tail of the buffer. Returns pointer to the copied
653 * data area. Returns NULL on error.
657 * ---------------------------------
658 * | head | data | tail |
659 * ---------------------------------
661 * Puts data to the tail section.
663 * silc_buffer_put_tail(sb, data, data_len);
668 unsigned char *silc_buffer_put_tail(SilcBuffer sb,
669 const unsigned char *data,
672 #if defined(SILC_DEBUG)
673 SILC_ASSERT(len <= silc_buffer_taillen(sb));
675 if (silc_unlikely(len > silc_buffer_taillen(sb)))
678 return (unsigned char *)memcpy(sb->tail, data, len);
681 /****f* silcutil/SilcBufferAPI/silc_buffer_alloc_size
686 * SilcBuffer silc_buffer_alloc_size(SilcUInt32 len);
690 * Allocates `len' bytes size buffer and moves the tail area automatically
691 * `len' bytes so that the buffer is ready to use without calling the
692 * silc_buffer_pull_tail. Returns NULL on error.
697 SilcBuffer silc_buffer_alloc_size(SilcUInt32 len)
699 SilcBuffer sb = silc_buffer_alloc(len);
700 if (silc_unlikely(!sb))
702 silc_buffer_pull_tail(sb, len);
706 /****f* silcutil/SilcBufferAPI/silc_buffer_reset
711 * void silc_buffer_reset(SilcBuffer sb);
715 * Resets the buffer to the state as if it was just allocated by
716 * silc_buffer_alloc. This does not clear the data area. Use
717 * silc_buffer_clear if you also want to clear the data area.
722 void silc_buffer_reset(SilcBuffer sb)
724 sb->data = sb->tail = sb->head;
727 /****f* silcutil/SilcBufferAPI/silc_buffer_clear
732 * void silc_buffer_clear(SilcBuffer sb);
736 * Clears and initialiazes the buffer to the state as if it was just
737 * allocated by silc_buffer_alloc.
742 void silc_buffer_clear(SilcBuffer sb)
744 memset(sb->head, 0, silc_buffer_truelen(sb));
745 silc_buffer_reset(sb);
748 /****f* silcutil/SilcBufferAPI/silc_buffer_start
753 * void silc_buffer_start(SilcBuffer sb);
757 * Moves the data area at the start of the buffer. The tail area remains
763 void silc_buffer_start(SilcBuffer sb)
768 /****f* silcutil/SilcBufferAPI/silc_buffer_end
773 * void silc_buffer_end(SilcBuffer sb);
777 * Moves the end of the data area to the end of the buffer. The start
778 * of the data area remains same. If the start of data area is at the
779 * start of the buffer, after this function returns the buffer's data
780 * area length is the length of the entire buffer.
785 void silc_buffer_end(SilcBuffer sb)
790 /****f* silcutil/SilcBufferAPI/silc_buffer_copy
795 * SilcBuffer silc_buffer_copy(SilcBuffer sb);
799 * Generates copy of a SilcBuffer. This copies everything inside the
800 * currently valid data area, nothing more. Use silc_buffer_clone to
801 * copy entire buffer. Returns NULL on error.
806 SilcBuffer silc_buffer_copy(SilcBuffer sb)
810 sb_new = silc_buffer_alloc_size(silc_buffer_len(sb));
811 if (silc_unlikely(!sb_new))
813 silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
818 /****f* silcutil/SilcBufferAPI/silc_buffer_clone
823 * SilcBuffer silc_buffer_clone(SilcBuffer sb);
827 * Clones SilcBuffer. This generates new SilcBuffer and copies
828 * everything from the source buffer. The result is exact clone of
829 * the original buffer. Returns NULL on error.
834 SilcBuffer silc_buffer_clone(SilcBuffer sb)
838 sb_new = silc_buffer_alloc_size(silc_buffer_truelen(sb));
839 if (silc_unlikely(!sb_new))
841 silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
842 sb_new->data = sb_new->head + silc_buffer_headlen(sb);
843 sb_new->tail = sb_new->data + silc_buffer_len(sb);
848 /****f* silcutil/SilcBufferAPI/silc_buffer_realloc
853 * SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize);
857 * Reallocates buffer. Old data is saved into the new buffer. The buffer
858 * is exact clone of the old one except that there is now more space
859 * at the end of buffer. This always returns the same `sb' unless `sb'
860 * was NULL. Returns NULL on error.
865 SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize)
867 SilcUInt32 hlen, dlen;
871 return silc_buffer_alloc(newsize);
873 if (silc_unlikely(newsize <= silc_buffer_truelen(sb)))
876 hlen = silc_buffer_headlen(sb);
877 dlen = silc_buffer_len(sb);
878 h = (unsigned char *)silc_realloc(sb->head, newsize);
879 if (silc_unlikely(!h))
882 sb->data = sb->head + hlen;
883 sb->tail = sb->data + dlen;
884 sb->end = sb->head + newsize;
889 /****f* silcutil/SilcBufferAPI/silc_buffer_realloc_size
894 * SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize);
898 * Same as silc_buffer_realloc but moves moves the tail area
899 * automatically so that the buffer is ready to use without calling the
900 * silc_buffer_pull_tail. Returns NULL on error.
905 SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize)
907 sb = silc_buffer_realloc(sb, newsize);
908 if (silc_unlikely(!sb))
910 silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
914 /****f* silcutil/SilcBufferAPI/silc_buffer_enlarge
919 * SilcBuffer silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size);
923 * Enlarges the buffer by the amount of `size' if it doesn't have that
924 * must space in the data area and in the tail area. Moves the tail
925 * area automatically after enlarging so that the current data area
926 * is at least the size of `size'. If there is more space than `size'
927 * in the data area this does not do anything. If there is enough
928 * space in the tail area this merely moves the tail area to reveal
929 * the extra space. Returns FALSE on error.
934 SilcBool silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size)
936 if (size > silc_buffer_len(sb)) {
937 if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
938 if (silc_unlikely(!silc_buffer_realloc(sb, silc_buffer_truelen(sb) +
939 (size - silc_buffer_taillen(sb) -
940 silc_buffer_len(sb)))))
942 silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
948 /* SilcStack aware SilcBuffer routines */
950 /****f* silcutil/SilcBufferAPI/silc_buffer_salloc
955 * SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len);
959 * Allocates new SilcBuffer and returns it.
961 * This routine use SilcStack are memory source. If `stack' is NULL
962 * reverts back to normal allocating routine.
964 * Note that this call consumes the `stack'. The caller should push the
965 * stack before calling the function and pop it later.
970 SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len)
975 return silc_buffer_alloc(len);
977 /* Allocate new SilcBuffer */
978 sb = (SilcBuffer)silc_scalloc(stack, 1, sizeof(*sb));
979 if (silc_unlikely(!sb))
982 /* Allocate the actual data area */
983 sb->head = (unsigned char *)silc_smalloc(stack, len);
984 if (silc_unlikely(!sb->head))
987 /* Set pointers to the new buffer */
990 sb->end = sb->head + len;
995 /****f* silcutil/SilcBufferAPI/silc_buffer_salloc_size
1000 * SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len);
1004 * Allocates `len' bytes size buffer and moves the tail area automatically
1005 * `len' bytes so that the buffer is ready to use without calling the
1006 * silc_buffer_pull_tail.
1008 * This routine use SilcStack are memory source. If `stack' is NULL
1009 * reverts back to normal allocating routine.
1011 * Note that this call consumes the `stack'. The caller should push the
1012 * stack before calling the function and pop it later.
1017 SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len)
1019 SilcBuffer sb = silc_buffer_salloc(stack, len);
1020 if (silc_unlikely(!sb))
1022 silc_buffer_pull_tail(sb, len);
1026 /****f* silcutil/SilcBufferAPI/silc_buffer_srealloc
1031 * SilcBuffer silc_buffer_srealloc(SilcStack stack,
1032 * SilcBuffer sb, SilcUInt32 newsize);
1036 * Reallocates buffer. Old data is saved into the new buffer. The buffer
1037 * is exact clone of the old one except that there is now more space
1038 * at the end of buffer.
1040 * This routine use SilcStack are memory source. If `stack' is NULL
1041 * reverts back to normal allocating routine.
1043 * Note that this call consumes the `stack'. The caller should push the
1044 * stack before calling the function and pop it later.
1049 SilcBuffer silc_buffer_srealloc(SilcStack stack,
1050 SilcBuffer sb, SilcUInt32 newsize)
1052 SilcUInt32 hlen, dlen;
1056 return silc_buffer_realloc(sb, newsize);
1059 return silc_buffer_salloc(stack, newsize);
1061 if (newsize <= silc_buffer_truelen(sb))
1064 hlen = silc_buffer_headlen(sb);
1065 dlen = silc_buffer_len(sb);
1066 h = (unsigned char *)silc_srealloc(stack, silc_buffer_truelen(sb),
1069 /* Do slow and stack wasting realloc. The old sb->head is lost and
1070 is freed eventually. */
1071 h = (unsigned char *)silc_smalloc(stack, newsize);
1072 if (silc_unlikely(!h))
1074 memcpy(h, sb->head, silc_buffer_truelen(sb));
1078 sb->data = sb->head + hlen;
1079 sb->tail = sb->data + dlen;
1080 sb->end = sb->head + newsize;
1085 /****f* silcutil/SilcBufferAPI/silc_buffer_srealloc_size
1090 * SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1091 * SilcBuffer sb, SilcUInt32 newsize);
1095 * Same as silc_buffer_srealloc but moves moves the tail area
1096 * automatically so that the buffer is ready to use without calling the
1097 * silc_buffer_pull_tail.
1099 * This routine use SilcStack are memory source. If `stack' is NULL
1100 * reverts back to normal allocating routine.
1102 * Note that this call consumes the `stack'. The caller should push the
1103 * stack before calling the function and pop it later.
1108 SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1109 SilcBuffer sb, SilcUInt32 newsize)
1111 sb = silc_buffer_srealloc(stack, sb, newsize);
1112 if (silc_unlikely(!sb))
1114 silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
1118 /****f* silcutil/SilcBufferAPI/silc_buffer_senlarge
1123 * SilcBuffer silc_buffer_senlarge(SilcStack stack, SilcBuffer sb,
1128 * Enlarges the buffer by the amount of `size' if it doesn't have that
1129 * must space in the data area and in the tail area. Moves the tail
1130 * area automatically after enlarging so that the current data area
1131 * is at least the size of `size'. If there is more space than `size'
1132 * in the data area this does not do anything. If there is enough
1133 * space in the tail area this merely moves the tail area to reveal
1134 * the extra space. Returns FALSE on error.
1136 * This routine use SilcStack are memory source. If `stack' is NULL
1137 * reverts back to normal allocating routine.
1139 * Note that this call consumes the `stack'. The caller should push the
1140 * stack before calling the function and pop it later.
1145 SilcBool silc_buffer_senlarge(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
1147 if (size > silc_buffer_len(sb)) {
1148 if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
1149 if (silc_unlikely(!silc_buffer_srealloc(stack, sb,
1150 silc_buffer_truelen(sb) +
1151 (size - silc_buffer_taillen(sb) -
1152 silc_buffer_len(sb)))))
1154 silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
1159 /****f* silcutil/SilcBufferAPI/silc_buffer_scopy
1164 * SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb);
1168 * Generates copy of a SilcBuffer. This copies everything inside the
1169 * currently valid data area, nothing more. Use silc_buffer_clone to
1170 * copy entire buffer.
1172 * This routine use SilcStack are memory source. If `stack' is NULL
1173 * reverts back to normal allocating routine.
1175 * Note that this call consumes the `stack'. The caller should push the
1176 * stack before calling the function and pop it later.
1181 SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb)
1185 sb_new = silc_buffer_salloc_size(stack, silc_buffer_len(sb));
1186 if (silc_unlikely(!sb_new))
1188 silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
1193 /****f* silcutil/SilcBufferAPI/silc_buffer_sclone
1198 * SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb);
1202 * Clones SilcBuffer. This generates new SilcBuffer and copies
1203 * everything from the source buffer. The result is exact clone of
1204 * the original buffer.
1206 * This routine use SilcStack are memory source. If `stack' is NULL
1207 * reverts back to normal allocating routine.
1209 * Note that this call consumes the `stack'. The caller should push the
1210 * stack before calling the function and pop it later.
1215 SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb)
1219 sb_new = silc_buffer_salloc_size(stack, silc_buffer_truelen(sb));
1220 if (silc_unlikely(!sb_new))
1222 silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
1223 sb_new->data = sb_new->head + silc_buffer_headlen(sb);
1224 sb_new->tail = sb_new->data + silc_buffer_len(sb);
1229 #endif /* SILCBUFFER_H */