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_malloc(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_salloc
275 * SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len);
279 * Allocates new SilcBuffer and returns it.
281 * This routine use SilcStack are memory source. If `stack' is NULL
282 * reverts back to normal allocating routine.
284 * Note that this call consumes the `stack'. The caller should push the
285 * stack before calling the function and pop it later.
290 SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len)
295 return silc_buffer_alloc(len);
297 /* Allocate new SilcBuffer */
298 sb = (SilcBuffer)silc_scalloc(stack, 1, sizeof(*sb));
299 if (silc_unlikely(!sb))
302 if (silc_likely(len)) {
303 /* Allocate the actual data area */
304 sb->head = (unsigned char *)silc_smalloc(stack, len * sizeof(*sb->head));
305 if (silc_unlikely(!sb->head))
308 /* Set pointers to the new buffer */
311 sb->end = sb->head + len;
317 /****f* silcutil/SilcBufferAPI/silc_buffer_free
322 * void silc_buffer_free(SilcBuffer sb);
326 * Frees SilcBuffer. Can be called safely `sb' as NULL.
330 * Must not be called for buffers allocated with silc_buffer_salloc,
331 * silc_buffer_salloc_size, silc_buffer_scopy and silc_buffer_sclone.
332 * Call silc_buffer_sfree instead.
337 void silc_buffer_free(SilcBuffer sb)
340 #if defined(SILC_DEBUG)
342 memset(sb->head, 'F', silc_buffer_truelen(sb));
349 /****f* silcutil/SilcBufferAPI/silc_buffer_sfree
354 * void silc_buffer_free(SilcStack stack, SilcBuffer sb);
358 * Frees SilcBuffer. If `stack' is NULL this calls silc_buffer_free. Can
359 * be called safely `sb' as NULL.
364 void silc_buffer_sfree(SilcStack stack, SilcBuffer sb)
370 memset(sb->head, 'F', silc_buffer_truelen(sb));
371 memset(sb, 'F', sizeof(*sb));
373 #endif /* SILC_DEBUG */
377 silc_buffer_free(sb);
380 /****f* silcutil/SilcBufferAPI/silc_buffer_steal
385 * unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len);
389 * Steals the data from the buffer `sb'. This returns pointer to the
390 * start of the buffer and the true length of that buffer. The `sb'
391 * cannot be used anymore after calling this function because the
392 * data buffer was stolen. The `sb' must be freed with silc_buffer_free.
393 * The caller is responsible of freeing the stolen data buffer with
399 unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
401 unsigned char *buf = sb->head;
403 *data_len = silc_buffer_truelen(sb);
404 sb->head = sb->data = sb->tail = sb->end = NULL;
408 /****f* silcutil/SilcBufferAPI/silc_buffer_purge
413 * void silc_buffer_purge(SilcBuffer sb);
417 * Same as silc_buffer_free but free's only the contents of the buffer
418 * not the buffer itself. The `sb' remains intact, data is freed. Buffer
419 * is ready for re-use after calling this function.
423 * Must not be called for buffers allocated with silc_buffer_salloc,
424 * silc_buffer_salloc_size, silc_buffer_scopy and silc_buffer_sclone.
425 * Use silc_buffer_spurge instead.
430 void silc_buffer_purge(SilcBuffer sb)
432 silc_free(silc_buffer_steal(sb, NULL));
435 /****f* silcutil/SilcBufferAPI/silc_buffer_spurge
440 * void silc_buffer_spurge(SilcStack stack, SilcBuffer sb);
444 * Same as silc_buffer_free but free's only the contents of the buffer
445 * not the buffer itself. The `sb' remains intact, data is freed. Buffer
446 * is ready for re-use after calling this function. If `stack' is NULL
447 * this calls silc_buffer_purge.
452 void silc_buffer_spurge(SilcStack stack, SilcBuffer sb)
457 memset(silc_buffer_steal(sb, NULL), 'F', silc_buffer_truelen(sb));
458 #endif /* SILC_DEBUG */
462 silc_buffer_purge(sb);
465 /****f* silcutil/SilcBufferAPI/silc_buffer_set
470 * void silc_buffer_set(SilcBuffer sb,
471 * unsigned char *data,
472 * SilcUInt32 data_len);
476 * Sets the `data' and `data_len' to the buffer pointer sent as argument.
477 * The data area is automatically set to the `data_len'. This function
478 * can be used to set the data to static buffer without needing any
479 * memory allocations. The `data' will not be copied to the buffer.
483 * SilcBufferStruct buf;
484 * silc_buffer_set(&buf, data, data_len);
489 void silc_buffer_set(SilcBuffer sb, unsigned char *data, SilcUInt32 data_len)
491 sb->data = sb->head = data;
492 sb->tail = sb->end = data + data_len;
495 /****f* silcutil/SilcBufferAPI/silc_buffer_pull
500 * unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len);
504 * Pulls current data area towards end. The length of the currently
505 * valid data area is also decremented. Returns pointer to the data
506 * area before pulling. Returns NULL on error.
510 * ---------------------------------
511 * | head | data | tail |
512 * ---------------------------------
514 * Pulls the start of the data area.
516 * ---------------------------------
517 * | head | data | tail |
518 * ---------------------------------
521 * silc_buffer_pull(sb, 20);
526 unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len)
528 unsigned char *old_data = sb->data;
529 #if defined(SILC_DEBUG)
530 SILC_ASSERT(len <= silc_buffer_len(sb));
532 if (silc_unlikely(len > silc_buffer_len(sb)))
539 /****f* silcutil/SilcBufferAPI/silc_buffer_push
544 * unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len);
548 * Pushes current data area towards beginning. Length of the currently
549 * valid data area is also incremented. Returns a pointer to the
550 * data area before pushing. Returns NULL on error.
554 * ---------------------------------
555 * | head | data | tail |
556 * ---------------------------------
558 * Pushes the start of the data area.
560 * ---------------------------------
561 * | head | data | tail |
562 * ---------------------------------
565 * silc_buffer_push(sb, 20);
570 unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len)
572 unsigned char *old_data = sb->data;
573 #if defined(SILC_DEBUG)
574 SILC_ASSERT((sb->data - len) >= sb->head);
576 if (silc_unlikely((sb->data - len) < sb->head))
583 /****f* silcutil/SilcBufferAPI/silc_buffer_pull_tail
588 * unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len);
592 * Pulls current tail section towards end. Length of the current valid
593 * data area is also incremented. Returns a pointer to the data area
594 * before pulling. Returns NULL on error.
598 * ---------------------------------
599 * | head | data | tail |
600 * ---------------------------------
602 * Pulls the start of the tail section.
604 * ---------------------------------
605 * | head | data | tail |
606 * ---------------------------------
609 * silc_buffer_pull_tail(sb, 23);
614 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len)
616 unsigned char *old_tail = sb->tail;
617 #if defined(SILC_DEBUG)
618 SILC_ASSERT(len <= silc_buffer_taillen(sb));
620 if (silc_unlikely(len > silc_buffer_taillen(sb)))
627 /****f* silcutil/SilcBufferAPI/silc_buffer_push_tail
632 * unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len);
636 * Pushes current tail section towards beginning. Length of the current
637 * valid data area is also decremented. Returns a pointer to the
638 * tail section before pushing. Returns NULL on error.
642 * ---------------------------------
643 * | head | data | tail |
644 * ---------------------------------
646 * Pushes the start of the tail section.
648 * ---------------------------------
649 * | head | data | tail |
650 * ---------------------------------
653 * silc_buffer_push_tail(sb, 23);
658 unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len)
660 unsigned char *old_tail = sb->tail;
661 #if defined(SILC_DEBUG)
662 SILC_ASSERT((sb->tail - len) >= sb->data);
664 if (silc_unlikely((sb->tail - len) < sb->data))
671 /****f* silcutil/SilcBufferAPI/silc_buffer_put_head
676 * unsigned char *silc_buffer_put_head(SilcBuffer sb,
677 * const unsigned char *data,
682 * Puts data at the head of the buffer. Returns pointer to the copied
683 * data area. Returns NULL on error.
687 * ---------------------------------
688 * | head | data | tail |
689 * ---------------------------------
691 * Puts data to the head section.
693 * silc_buffer_put_head(sb, data, data_len);
698 unsigned char *silc_buffer_put_head(SilcBuffer sb,
699 const unsigned char *data,
702 #if defined(SILC_DEBUG)
703 SILC_ASSERT(len <= silc_buffer_headlen(sb));
705 if (silc_unlikely(len > silc_buffer_headlen(sb)))
708 return (unsigned char *)memcpy(sb->head, data, len);
711 /****f* silcutil/SilcBufferAPI/silc_buffer_put
716 * unsigned char *silc_buffer_put(SilcBuffer sb,
717 * const unsigned char *data,
722 * Puts data at the start of the valid data area. Returns a pointer
723 * to the copied data area. Returns NULL on error.
727 * ---------------------------------
728 * | head | data | tail |
729 * ---------------------------------
731 * Puts data to the data section.
733 * silc_buffer_put(sb, data, data_len);
738 unsigned char *silc_buffer_put(SilcBuffer sb,
739 const unsigned char *data,
742 #if defined(SILC_DEBUG)
743 SILC_ASSERT(len <= silc_buffer_len(sb));
745 if (silc_unlikely(len > silc_buffer_len(sb)))
748 return (unsigned char *)memcpy(sb->data, data, len);
751 /****f* silcutil/SilcBufferAPI/silc_buffer_put_tail
756 * unsigned char *silc_buffer_put_tail(SilcBuffer sb,
757 * const unsigned char *data,
762 * Puts data at the tail of the buffer. Returns pointer to the copied
763 * data area. Returns NULL on error.
767 * ---------------------------------
768 * | head | data | tail |
769 * ---------------------------------
771 * Puts data to the tail section.
773 * silc_buffer_put_tail(sb, data, data_len);
778 unsigned char *silc_buffer_put_tail(SilcBuffer sb,
779 const unsigned char *data,
782 #if defined(SILC_DEBUG)
783 SILC_ASSERT(len <= silc_buffer_taillen(sb));
785 if (silc_unlikely(len > silc_buffer_taillen(sb)))
788 return (unsigned char *)memcpy(sb->tail, data, len);
791 /****f* silcutil/SilcBufferAPI/silc_buffer_alloc_size
796 * SilcBuffer silc_buffer_alloc_size(SilcUInt32 len);
800 * Allocates `len' bytes size buffer and moves the tail area automatically
801 * `len' bytes so that the buffer is ready to use without calling the
802 * silc_buffer_pull_tail. Returns NULL on error.
807 SilcBuffer silc_buffer_alloc_size(SilcUInt32 len)
809 SilcBuffer sb = silc_buffer_alloc(len);
810 if (silc_unlikely(!sb))
812 silc_buffer_pull_tail(sb, len);
816 /****f* silcutil/SilcBufferAPI/silc_buffer_salloc_size
821 * SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len);
825 * Allocates `len' bytes size buffer and moves the tail area automatically
826 * `len' bytes so that the buffer is ready to use without calling the
827 * silc_buffer_pull_tail.
829 * This routine use SilcStack are memory source. If `stack' is NULL
830 * reverts back to normal allocating routine.
832 * Note that this call consumes the `stack'. The caller should push the
833 * stack before calling the function and pop it later.
838 SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len)
840 SilcBuffer sb = silc_buffer_salloc(stack, len);
841 if (silc_unlikely(!sb))
843 silc_buffer_pull_tail(sb, len);
847 /****f* silcutil/SilcBufferAPI/silc_buffer_reset
852 * void silc_buffer_reset(SilcBuffer sb);
856 * Resets the buffer to the state as if it was just allocated by
857 * silc_buffer_alloc. This does not clear the data area. Use
858 * silc_buffer_clear if you also want to clear the data area.
863 void silc_buffer_reset(SilcBuffer sb)
865 sb->data = sb->tail = sb->head;
868 /****f* silcutil/SilcBufferAPI/silc_buffer_clear
873 * void silc_buffer_clear(SilcBuffer sb);
877 * Clears and initialiazes the buffer to the state as if it was just
878 * allocated by silc_buffer_alloc.
883 void silc_buffer_clear(SilcBuffer sb)
885 memset(sb->head, 0, silc_buffer_truelen(sb));
886 silc_buffer_reset(sb);
889 /****f* silcutil/SilcBufferAPI/silc_buffer_start
894 * void silc_buffer_start(SilcBuffer sb);
898 * Moves the data area at the start of the buffer. The tail area remains
904 void silc_buffer_start(SilcBuffer sb)
909 /****f* silcutil/SilcBufferAPI/silc_buffer_end
914 * void silc_buffer_end(SilcBuffer sb);
918 * Moves the end of the data area to the end of the buffer. The start
919 * of the data area remains same. If the start of data area is at the
920 * start of the buffer, after this function returns the buffer's data
921 * area length is the length of the entire buffer.
926 void silc_buffer_end(SilcBuffer sb)
931 /****f* silcutil/SilcBufferAPI/silc_buffer_copy
936 * SilcBuffer silc_buffer_copy(SilcBuffer sb);
940 * Generates copy of a SilcBuffer. This copies everything inside the
941 * currently valid data area, nothing more. Use silc_buffer_clone to
942 * copy entire buffer. Returns NULL on error.
947 SilcBuffer silc_buffer_copy(SilcBuffer sb)
951 sb_new = silc_buffer_alloc_size(silc_buffer_len(sb));
952 if (silc_unlikely(!sb_new))
954 silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
959 /****f* silcutil/SilcBufferAPI/silc_buffer_scopy
964 * SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb);
968 * Generates copy of a SilcBuffer. This copies everything inside the
969 * currently valid data area, nothing more. Use silc_buffer_clone to
970 * copy entire buffer.
972 * This routine use SilcStack are memory source. If `stack' is NULL
973 * reverts back to normal allocating routine.
975 * Note that this call consumes the `stack'. The caller should push the
976 * stack before calling the function and pop it later.
981 SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb)
985 sb_new = silc_buffer_salloc_size(stack, silc_buffer_len(sb));
986 if (silc_unlikely(!sb_new))
988 silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
993 /****f* silcutil/SilcBufferAPI/silc_buffer_clone
998 * SilcBuffer silc_buffer_clone(SilcBuffer sb);
1002 * Clones SilcBuffer. This generates new SilcBuffer and copies
1003 * everything from the source buffer. The result is exact clone of
1004 * the original buffer. Returns NULL on error.
1009 SilcBuffer silc_buffer_clone(SilcBuffer sb)
1013 sb_new = silc_buffer_alloc_size(silc_buffer_truelen(sb));
1014 if (silc_unlikely(!sb_new))
1016 silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
1017 sb_new->data = sb_new->head + silc_buffer_headlen(sb);
1018 sb_new->tail = sb_new->data + silc_buffer_len(sb);
1023 /****f* silcutil/SilcBufferAPI/silc_buffer_sclone
1028 * SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb);
1032 * Clones SilcBuffer. This generates new SilcBuffer and copies
1033 * everything from the source buffer. The result is exact clone of
1034 * the original buffer.
1036 * This routine use SilcStack are memory source. If `stack' is NULL
1037 * reverts back to normal allocating routine.
1039 * Note that this call consumes the `stack'. The caller should push the
1040 * stack before calling the function and pop it later.
1045 SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb)
1049 sb_new = silc_buffer_salloc_size(stack, silc_buffer_truelen(sb));
1050 if (silc_unlikely(!sb_new))
1052 silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
1053 sb_new->data = sb_new->head + silc_buffer_headlen(sb);
1054 sb_new->tail = sb_new->data + silc_buffer_len(sb);
1059 /****f* silcutil/SilcBufferAPI/silc_buffer_realloc
1064 * SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize);
1068 * Reallocates buffer. Old data is saved into the new buffer. The buffer
1069 * is exact clone of the old one except that there is now more space
1070 * at the end of buffer. This always returns the same `sb' unless `sb'
1071 * was NULL. Returns NULL on error.
1076 SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize)
1078 SilcUInt32 hlen, dlen;
1082 return silc_buffer_alloc(newsize);
1084 if (silc_unlikely(newsize <= silc_buffer_truelen(sb)))
1087 hlen = silc_buffer_headlen(sb);
1088 dlen = silc_buffer_len(sb);
1089 h = (unsigned char *)silc_realloc(sb->head, newsize);
1090 if (silc_unlikely(!h))
1093 sb->data = sb->head + hlen;
1094 sb->tail = sb->data + dlen;
1095 sb->end = sb->head + newsize;
1100 /****f* silcutil/SilcBufferAPI/silc_buffer_srealloc
1105 * SilcBuffer silc_buffer_srealloc(SilcStack stack,
1106 * SilcBuffer sb, SilcUInt32 newsize);
1110 * Reallocates buffer. Old data is saved into the new buffer. The buffer
1111 * is exact clone of the old one except that there is now more space
1112 * at the end of buffer.
1114 * This routine use SilcStack are memory source. If `stack' is NULL
1115 * reverts back to normal allocating routine.
1117 * Note that this call consumes the `stack'. The caller should push the
1118 * stack before calling the function and pop it later.
1123 SilcBuffer silc_buffer_srealloc(SilcStack stack,
1124 SilcBuffer sb, SilcUInt32 newsize)
1126 SilcUInt32 hlen, dlen;
1130 return silc_buffer_realloc(sb, newsize);
1133 return silc_buffer_salloc(stack, newsize);
1135 if (newsize <= silc_buffer_truelen(sb))
1138 hlen = silc_buffer_headlen(sb);
1139 dlen = silc_buffer_len(sb);
1140 h = (unsigned char *)silc_srealloc(stack, silc_buffer_truelen(sb),
1143 /* Do slow and stack wasting realloc. The old sb->head is lost and
1144 is freed eventually. */
1145 h = (unsigned char *)silc_smalloc(stack, newsize);
1146 if (silc_unlikely(!h))
1148 memcpy(h, sb->head, silc_buffer_truelen(sb));
1152 sb->data = sb->head + hlen;
1153 sb->tail = sb->data + dlen;
1154 sb->end = sb->head + newsize;
1159 /****f* silcutil/SilcBufferAPI/silc_buffer_realloc_size
1164 * SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize);
1168 * Same as silc_buffer_realloc but moves moves the tail area
1169 * automatically so that the buffer is ready to use without calling the
1170 * silc_buffer_pull_tail. Returns NULL on error.
1175 SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize)
1177 sb = silc_buffer_realloc(sb, newsize);
1178 if (silc_unlikely(!sb))
1180 silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
1184 /****f* silcutil/SilcBufferAPI/silc_buffer_srealloc_size
1189 * SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1190 * SilcBuffer sb, SilcUInt32 newsize);
1194 * Same as silc_buffer_srealloc but moves moves the tail area
1195 * automatically so that the buffer is ready to use without calling the
1196 * silc_buffer_pull_tail.
1198 * This routine use SilcStack are memory source. If `stack' is NULL
1199 * reverts back to normal allocating routine.
1201 * Note that this call consumes the `stack'. The caller should push the
1202 * stack before calling the function and pop it later.
1207 SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1208 SilcBuffer sb, SilcUInt32 newsize)
1210 sb = silc_buffer_srealloc(stack, sb, newsize);
1211 if (silc_unlikely(!sb))
1213 silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
1217 /****f* silcutil/SilcBufferAPI/silc_buffer_enlarge
1222 * SilcBuffer silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size);
1226 * Enlarges the buffer by the amount of `size' if it doesn't have that
1227 * must space in the data area and in the tail area. Moves the tail
1228 * area automatically after enlarging so that the current data area
1229 * is at least the size of `size'. If there is more space than `size'
1230 * in the data area this does not do anything. If there is enough
1231 * space in the tail area this merely moves the tail area to reveal
1232 * the extra space. Returns FALSE on error.
1237 SilcBool silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size)
1239 if (size > silc_buffer_len(sb)) {
1240 if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
1241 if (silc_unlikely(!silc_buffer_realloc(sb, silc_buffer_truelen(sb) +
1242 (size - silc_buffer_taillen(sb) -
1243 silc_buffer_len(sb)))))
1245 silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
1250 /****f* silcutil/SilcBufferAPI/silc_buffer_senlarge
1255 * SilcBuffer silc_buffer_senlarge(SilcStack stack, SilcBuffer sb,
1260 * Enlarges the buffer by the amount of `size' if it doesn't have that
1261 * must space in the data area and in the tail area. Moves the tail
1262 * area automatically after enlarging so that the current data area
1263 * is at least the size of `size'. If there is more space than `size'
1264 * in the data area this does not do anything. If there is enough
1265 * space in the tail area this merely moves the tail area to reveal
1266 * the extra space. Returns FALSE on error.
1268 * This routine use SilcStack are memory source. If `stack' is NULL
1269 * reverts back to normal allocating routine.
1271 * Note that this call consumes the `stack'. The caller should push the
1272 * stack before calling the function and pop it later.
1277 SilcBool silc_buffer_senlarge(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
1279 if (size > silc_buffer_len(sb)) {
1280 if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
1281 if (silc_unlikely(!silc_buffer_srealloc(stack, sb,
1282 silc_buffer_truelen(sb) +
1283 (size - silc_buffer_taillen(sb) -
1284 silc_buffer_len(sb)))))
1286 silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
1291 #endif /* SILCBUFFER_H */