5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1998 - 2008 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.
20 /****h* silcutil/Buffer Interface
24 * Data buffer interface that provides buffer allocation and manipulation
25 * routines. SilcBuffer is 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. See the SilcBuffer context for more information.
30 * The SilcBuffer context is not thread-safe and if same context must be
31 * used from multiple threads concurrency control must be employed.
38 /****s* silcutil/SilcBuffer
42 * typedef struct { ... } *SilcBuffer, SilcBufferStruct;
46 * SILC Buffer object. Following short description of the fields
51 * Head of the allocated buffer. This is the start of the allocated
52 * data area and remains as same throughout the lifetime of the buffer.
53 * However, the end of the head area or the start of the currently valid
54 * data area is variable. Reallocating the buffer may change the
57 * --------------------------------
58 * | head | data | tail |
59 * --------------------------------
62 * Current head section in the buffer is sb->data - sb->head.
64 * unsigned char *data;
66 * Currently valid data area. This is the start of the currently valid
67 * main data area. The data area is variable in all directions.
69 * --------------------------------
70 * | head | data | tail |
71 * --------------------------------
74 * Current valid data area in the buffer is sb->tail - sb->data.
76 * unsigned char *tail;
78 * Tail of the buffer. This is the end of the currently valid data area
79 * or start of the tail area. The start of the tail area is variable.
81 * --------------------------------
82 * | head | data | tail |
83 * --------------------------------
86 * Current tail section in the buffer is sb->end - sb->tail.
90 * End of the allocated buffer. This is the end of the allocated data
91 * area and remains as same throughout the lifetime of the buffer.
92 * Usually this field is not needed except when checking the size
95 * --------------------------------
96 * | head | data | tail |
97 * --------------------------------
100 * Length of the entire buffer is (ie. truelen) sb->end - sb->head.
102 * Currently valid data area is considered to be the main data area in
103 * the buffer. However, the entire buffer is of course valid data and can
104 * be used as such. Usually head section of the buffer includes different
105 * kind of headers or similar. Data section includes the main data of
106 * the buffer. Tail section can be seen as a reserve space of the data
107 * section. Tail section can be pulled towards end, and thus the data
108 * section becomes larger.
112 typedef struct SilcBufferObject {
113 unsigned char *head; /* Head of the allocated buffer area */
114 unsigned char *data; /* Start of the data area */
115 unsigned char *tail; /* Start of the tail area */
116 unsigned char *end; /* End of the buffer */
117 } *SilcBuffer, SilcBufferStruct;
122 /****f* silcutil/silc_buffer_data
126 * unsigned char *silc_buffer_data(SilcBuffer sb)
130 * Returns pointer to the data area of the buffer.
134 #define silc_buffer_data(x) (x)->data
137 /****f* silcutil/silc_buffer_tail
141 * unsigned char *silc_buffer_tail(SilcBuffer sb)
145 * Returns pointer to the tail area of the buffer.
149 #define silc_buffer_tail(x) (x)->tail
152 /****f* silcutil/silc_buffer_datalen
156 * #define silc_buffer_datalen ...
160 * Macro that can be used in function argument list to give the data
161 * pointer and the data length, instead of calling both silc_buffer_data
162 * and silc_buffer_len separately.
166 * // Following are the same thing
167 * silc_foo_function(foo, silc_buffer_datalen(buf));
168 * silc_foo_function(foo, silc_buffer_data(buf), silc_buffer_len(buf));
172 #define silc_buffer_datalen(x) (x) ? silc_buffer_data((x)) : NULL, \
173 (x) ? silc_buffer_len((x)) : 0
176 /* Inline functions */
178 /****d* silcutil/silc_buffer_truelen
182 * SilcUInt32 silc_buffer_truelen(SilcBuffer sb)
186 * Returns the true length of the buffer.
190 SilcUInt32 silc_buffer_truelen(SilcBuffer x)
192 return (SilcUInt32)(x->end - x->head);
195 /****d* silcutil/silc_buffer_len
199 * SilcUInt32 silc_buffer_len(SilcBuffer sb)
203 * Returns the current length of the data area of the buffer.
207 SilcUInt32 silc_buffer_len(SilcBuffer x)
209 return (SilcUInt32)(x->tail - x->data);
212 /****d* silcutil/silc_buffer_headlen
216 * SilcUInt32 silc_buffer_headlen(SilcBuffer sb)
220 * Returns the current length of the head data area of the buffer.
224 SilcUInt32 silc_buffer_headlen(SilcBuffer x)
226 return (SilcUInt32)(x->data - x->head);
229 /****d* silcutil/silc_buffer_taillen
233 * SilcUInt32 silc_buffer_taillen(SilcBuffer sb)
237 * Returns the current length of the tail data area of the buffer.
241 SilcUInt32 silc_buffer_taillen(SilcBuffer x)
243 return (SilcUInt32)(x->end - x->tail);
246 /****f* silcutil/silc_buffer_alloc
251 * SilcBuffer silc_buffer_alloc(SilcUInt32 len);
255 * Allocates new SilcBuffer and returns it. Returns NULL if system is
261 SilcBuffer silc_buffer_alloc(SilcUInt32 len)
265 /* Allocate new SilcBuffer */
266 sb = (SilcBuffer)silc_calloc(1, sizeof(*sb));
267 if (silc_unlikely(!sb))
270 if (silc_likely(len)) {
271 /* Allocate the actual data area */
272 sb->head = (unsigned char *)silc_malloc(len * sizeof(*sb->head));
273 if (silc_unlikely(!sb->head))
276 /* Set pointers to the new buffer */
279 sb->end = sb->head + len;
285 /****f* silcutil/silc_buffer_salloc
290 * SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len);
294 * Allocates new SilcBuffer and returns it. Returns NULL if system is
297 * This routine use SilcStack are memory source. If `stack' is NULL
298 * reverts back to normal allocating routine.
300 * Note that this call consumes the `stack'. The caller should push the
301 * stack before calling the function and pop it later.
306 SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len)
311 return silc_buffer_alloc(len);
313 /* Allocate new SilcBuffer */
314 sb = (SilcBuffer)silc_scalloc(stack, 1, sizeof(*sb));
315 if (silc_unlikely(!sb))
318 if (silc_likely(len)) {
319 /* Allocate the actual data area */
320 sb->head = (unsigned char *)silc_smalloc(stack, len * sizeof(*sb->head));
321 if (silc_unlikely(!sb->head))
324 /* Set pointers to the new buffer */
327 sb->end = sb->head + len;
333 /****f* silcutil/silc_buffer_free
338 * void silc_buffer_free(SilcBuffer sb);
342 * Frees SilcBuffer. Can be called safely `sb' as NULL.
346 * Must not be called for buffers allocated with silc_buffer_salloc,
347 * silc_buffer_salloc_size, silc_buffer_scopy and silc_buffer_sclone.
348 * Call silc_buffer_sfree instead.
353 void silc_buffer_free(SilcBuffer sb)
356 #if defined(SILC_DEBUG)
358 memset(sb->head, 'F', silc_buffer_truelen(sb));
365 /****f* silcutil/silc_buffer_sfree
370 * void silc_buffer_free(SilcStack stack, SilcBuffer sb);
374 * Frees SilcBuffer. If `stack' is NULL this calls silc_buffer_free. Can
375 * be called safely `sb' as NULL.
380 void silc_buffer_sfree(SilcStack stack, SilcBuffer sb)
386 memset(sb->head, 'F', silc_buffer_truelen(sb));
387 memset(sb, 'F', sizeof(*sb));
389 #endif /* SILC_DEBUG */
393 silc_buffer_free(sb);
396 /****f* silcutil/silc_buffer_steal
401 * unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len);
405 * Steals the data from the buffer `sb'. This returns pointer to the
406 * start of the buffer and the true length of that buffer. The `sb'
407 * cannot be used anymore after calling this function because the
408 * data buffer was stolen. The `sb' must be freed with silc_buffer_free.
409 * The caller is responsible of freeing the stolen data buffer with
415 unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
417 unsigned char *buf = sb->head;
419 *data_len = silc_buffer_truelen(sb);
420 sb->head = sb->data = sb->tail = sb->end = NULL;
424 /****f* silcutil/silc_buffer_purge
429 * void silc_buffer_purge(SilcBuffer sb);
433 * Same as silc_buffer_free but free's only the contents of the buffer
434 * not the buffer itself. The `sb' remains intact, data is freed. Buffer
435 * is ready for re-use after calling this function.
439 * Must not be called for buffers allocated with silc_buffer_salloc,
440 * silc_buffer_salloc_size, silc_buffer_scopy and silc_buffer_sclone.
441 * Use silc_buffer_spurge instead.
446 void silc_buffer_purge(SilcBuffer sb)
448 silc_free(silc_buffer_steal(sb, NULL));
451 /****f* silcutil/silc_buffer_spurge
456 * void silc_buffer_spurge(SilcStack stack, SilcBuffer sb);
460 * Same as silc_buffer_free but free's only the contents of the buffer
461 * not the buffer itself. The `sb' remains intact, data is freed. Buffer
462 * is ready for re-use after calling this function. If `stack' is NULL
463 * this calls silc_buffer_purge.
468 void silc_buffer_spurge(SilcStack stack, SilcBuffer sb)
473 memset(silc_buffer_steal(sb, NULL), 'F', silc_buffer_truelen(sb));
474 #endif /* SILC_DEBUG */
478 silc_buffer_purge(sb);
481 /****f* silcutil/silc_buffer_set
486 * void silc_buffer_set(SilcBuffer sb,
487 * unsigned char *data,
488 * SilcUInt32 data_len);
492 * Sets the `data' and `data_len' to the buffer pointer sent as argument.
493 * The data area is automatically set to the `data_len'. This function
494 * can be used to set the data to static buffer without needing any
495 * memory allocations. The `data' will not be copied to the buffer.
499 * SilcBufferStruct buf;
500 * silc_buffer_set(&buf, data, data_len);
505 void silc_buffer_set(SilcBuffer sb, unsigned char *data, SilcUInt32 data_len)
507 sb->data = sb->head = data;
508 sb->tail = sb->end = data + data_len;
511 /****f* silcutil/silc_buffer_pull
516 * unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len);
520 * Pulls current data area towards end. The length of the currently
521 * valid data area is also decremented. Returns pointer to the data
522 * area before pulling. Returns NULL if the pull would lead to buffer
523 * overflow or would go beyond the valid data area.
527 * ---------------------------------
528 * | head | data | tail |
529 * ---------------------------------
531 * Pulls the start of the data area.
533 * ---------------------------------
534 * | head | data | tail |
535 * ---------------------------------
538 * silc_buffer_pull(sb, 20);
543 unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len)
545 unsigned char *old_data = sb->data;
547 #ifdef SILC_DIST_INPLACE
548 SILC_ASSERT(len <= silc_buffer_len(sb));
549 #endif /* SILC_DIST_INPLACE */
550 if (silc_unlikely(len > silc_buffer_len(sb))) {
551 silc_set_errno(SILC_ERR_OVERFLOW);
559 /****f* silcutil/silc_buffer_push
564 * unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len);
568 * Pushes current data area towards beginning. Length of the currently
569 * valid data area is also incremented. Returns a pointer to the
570 * data area before pushing. Returns NULL if the push would lead to
571 * go beyond the buffer boundaries or current data area.
575 * ---------------------------------
576 * | head | data | tail |
577 * ---------------------------------
579 * Pushes the start of the data area.
581 * ---------------------------------
582 * | head | data | tail |
583 * ---------------------------------
586 * silc_buffer_push(sb, 20);
591 unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len)
593 unsigned char *old_data = sb->data;
595 #ifdef SILC_DIST_INPLACE
596 SILC_ASSERT((sb->data - len) >= sb->head);
597 #endif /* SILC_DIST_INPLACE */
598 if (silc_unlikely((sb->data - len) < sb->head)) {
599 silc_set_errno(SILC_ERR_OVERFLOW);
607 /****f* silcutil/silc_buffer_pull_tail
612 * unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len);
616 * Pulls current tail section towards end. Length of the current valid
617 * data area is also incremented. Returns a pointer to the data area
618 * before pulling. Returns NULL if the pull would lead to buffer overflow.
622 * ---------------------------------
623 * | head | data | tail |
624 * ---------------------------------
626 * Pulls the start of the tail section.
628 * ---------------------------------
629 * | head | data | tail |
630 * ---------------------------------
633 * silc_buffer_pull_tail(sb, 23);
638 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len)
640 unsigned char *old_tail = sb->tail;
642 #ifdef SILC_DIST_INPLACE
643 SILC_ASSERT(len <= silc_buffer_taillen(sb));
644 #endif /* SILC_DIST_INPLACE */
645 if (silc_unlikely(len > silc_buffer_taillen(sb))) {
646 silc_set_errno(SILC_ERR_OVERFLOW);
654 /****f* silcutil/silc_buffer_push_tail
659 * unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len);
663 * Pushes current tail section towards beginning. Length of the current
664 * valid data area is also decremented. Returns a pointer to the
665 * tail section before pushing. Returns NULL if the push would lead to
666 * go beyond buffer boundaries or current tail area.
670 * ---------------------------------
671 * | head | data | tail |
672 * ---------------------------------
674 * Pushes the start of the tail section.
676 * ---------------------------------
677 * | head | data | tail |
678 * ---------------------------------
681 * silc_buffer_push_tail(sb, 23);
686 unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len)
688 unsigned char *old_tail = sb->tail;
690 #ifdef SILC_DIST_INPLACE
691 SILC_ASSERT((sb->tail - len) >= sb->data);
692 #endif /* SILC_DIST_INPLACE */
693 if (silc_unlikely((sb->tail - len) < sb->data)) {
694 silc_set_errno(SILC_ERR_OVERFLOW);
702 /****f* silcutil/silc_buffer_put_head
707 * unsigned char *silc_buffer_put_head(SilcBuffer sb,
708 * const unsigned char *data,
713 * Puts data at the head of the buffer. Returns pointer to the copied
714 * data area. Returns NULL if the data is longer that the current head
719 * ---------------------------------
720 * | head | data | tail |
721 * ---------------------------------
723 * Puts data to the head section.
725 * silc_buffer_put_head(sb, data, data_len);
730 unsigned char *silc_buffer_put_head(SilcBuffer sb,
731 const unsigned char *data,
734 #ifdef SILC_DIST_INPLACE
735 SILC_ASSERT(len <= silc_buffer_headlen(sb));
736 #endif /* SILC_DIST_INPLACE */
737 if (silc_unlikely(len > silc_buffer_headlen(sb))) {
738 silc_set_errno(SILC_ERR_OVERFLOW);
742 if (sb->head > data) {
743 if (sb->head - data <= len)
744 return (unsigned char *)memmove(sb->head, data, len);
746 if (data - sb->head <= len)
747 return (unsigned char *)memmove(sb->head, data, len);
750 return (unsigned char *)memcpy(sb->head, data, len);
753 /****f* silcutil/silc_buffer_put
758 * unsigned char *silc_buffer_put(SilcBuffer sb,
759 * const unsigned char *data,
764 * Puts data at the start of the valid data area. Returns a pointer
765 * to the copied data area. Returns NULL if the data is longer than the
770 * ---------------------------------
771 * | head | data | tail |
772 * ---------------------------------
774 * Puts data to the data section.
776 * silc_buffer_put(sb, data, data_len);
781 unsigned char *silc_buffer_put(SilcBuffer sb,
782 const unsigned char *data,
785 #ifdef SILC_DIST_INPLACE
786 SILC_ASSERT(len <= silc_buffer_len(sb));
787 #endif /* SILC_DIST_INPLACE */
788 if (silc_unlikely(len > silc_buffer_len(sb))) {
789 silc_set_errno(SILC_ERR_OVERFLOW);
793 if (sb->data > data) {
794 if (sb->data - data <= len)
795 return (unsigned char *)memmove(sb->data, data, len);
797 if (data - sb->data <= len)
798 return (unsigned char *)memmove(sb->data, data, len);
801 return (unsigned char *)memcpy(sb->data, data, len);
804 /****f* silcutil/silc_buffer_put_tail
809 * unsigned char *silc_buffer_put_tail(SilcBuffer sb,
810 * const unsigned char *data,
815 * Puts data at the tail of the buffer. Returns pointer to the copied
816 * data area. Returns NULL if the data is longer than the current tail
821 * ---------------------------------
822 * | head | data | tail |
823 * ---------------------------------
825 * Puts data to the tail section.
827 * silc_buffer_put_tail(sb, data, data_len);
832 unsigned char *silc_buffer_put_tail(SilcBuffer sb,
833 const unsigned char *data,
836 #ifdef SILC_DIST_INPLACE
837 SILC_ASSERT(len <= silc_buffer_taillen(sb));
838 #endif /* SILC_DIST_INPLACE */
839 if (silc_unlikely(len > silc_buffer_taillen(sb))) {
840 silc_set_errno(SILC_ERR_OVERFLOW);
844 if (sb->tail > data) {
845 if (sb->tail - data <= len)
846 return (unsigned char *)memmove(sb->tail, data, len);
848 if (data - sb->tail <= len)
849 return (unsigned char *)memmove(sb->tail, data, len);
852 return (unsigned char *)memcpy(sb->tail, data, len);
855 /****f* silcutil/silc_buffer_alloc_size
860 * SilcBuffer silc_buffer_alloc_size(SilcUInt32 len);
864 * Allocates `len' bytes size buffer and moves the tail area automatically
865 * `len' bytes so that the buffer is ready to use without calling the
866 * silc_buffer_pull_tail. Returns NULL if system is out of memory.
871 SilcBuffer silc_buffer_alloc_size(SilcUInt32 len)
873 SilcBuffer sb = silc_buffer_alloc(len);
874 if (silc_unlikely(!sb))
876 silc_buffer_pull_tail(sb, len);
880 /****f* silcutil/silc_buffer_salloc_size
885 * SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len);
889 * Allocates `len' bytes size buffer and moves the tail area automatically
890 * `len' bytes so that the buffer is ready to use without calling the
891 * silc_buffer_pull_tail. Returns NULL if system is out of memory.
893 * This routine use SilcStack are memory source. If `stack' is NULL
894 * reverts back to normal allocating routine.
896 * Note that this call consumes the `stack'. The caller should push the
897 * stack before calling the function and pop it later.
902 SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len)
904 SilcBuffer sb = silc_buffer_salloc(stack, len);
905 if (silc_unlikely(!sb))
907 silc_buffer_pull_tail(sb, len);
911 /****f* silcutil/silc_buffer_reset
916 * void silc_buffer_reset(SilcBuffer sb);
920 * Resets the buffer to the state as if it was just allocated by
921 * silc_buffer_alloc. This does not clear the data area. Use
922 * silc_buffer_clear if you also want to clear the data area.
927 void silc_buffer_reset(SilcBuffer sb)
929 sb->data = sb->tail = sb->head;
932 /****f* silcutil/silc_buffer_clear
937 * void silc_buffer_clear(SilcBuffer sb);
941 * Clears and initialiazes the buffer to the state as if it was just
942 * allocated by silc_buffer_alloc.
947 void silc_buffer_clear(SilcBuffer sb)
949 memset(sb->head, 0, silc_buffer_truelen(sb));
950 silc_buffer_reset(sb);
953 /****f* silcutil/silc_buffer_start
958 * void silc_buffer_start(SilcBuffer sb);
962 * Moves the data area at the start of the buffer. The tail area remains
968 void silc_buffer_start(SilcBuffer sb)
973 /****f* silcutil/silc_buffer_end
978 * void silc_buffer_end(SilcBuffer sb);
982 * Moves the end of the data area to the end of the buffer. The start
983 * of the data area remains same. If the start of data area is at the
984 * start of the buffer, after this function returns the buffer's data
985 * area length is the length of the entire buffer.
990 void silc_buffer_end(SilcBuffer sb)
995 /****f* silcutil/silc_buffer_copy
1000 * SilcBuffer silc_buffer_copy(SilcBuffer sb);
1004 * Generates copy of a SilcBuffer. This copies everything inside the
1005 * currently valid data area, nothing more. Use silc_buffer_clone to
1006 * copy entire buffer. Returns NULL if system is out of memory.
1011 SilcBuffer silc_buffer_copy(SilcBuffer sb)
1015 sb_new = silc_buffer_alloc_size(silc_buffer_len(sb));
1016 if (silc_unlikely(!sb_new))
1018 silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
1023 /****f* silcutil/silc_buffer_scopy
1028 * SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb);
1032 * Generates copy of a SilcBuffer. This copies everything inside the
1033 * currently valid data area, nothing more. Use silc_buffer_clone to
1034 * copy entire buffer. Returns NULL if system is out of memory.
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_scopy(SilcStack stack, SilcBuffer sb)
1049 sb_new = silc_buffer_salloc_size(stack, silc_buffer_len(sb));
1050 if (silc_unlikely(!sb_new))
1052 silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
1057 /****f* silcutil/silc_buffer_clone
1062 * SilcBuffer silc_buffer_clone(SilcBuffer sb);
1066 * Clones SilcBuffer. This generates new SilcBuffer and copies
1067 * everything from the source buffer. The result is exact clone of
1068 * the original buffer. Returns NULL if system is out of memory.
1073 SilcBuffer silc_buffer_clone(SilcBuffer sb)
1077 sb_new = silc_buffer_alloc_size(silc_buffer_truelen(sb));
1078 if (silc_unlikely(!sb_new))
1080 silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
1081 sb_new->data = sb_new->head + silc_buffer_headlen(sb);
1082 sb_new->tail = sb_new->data + silc_buffer_len(sb);
1087 /****f* silcutil/silc_buffer_sclone
1092 * SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb);
1096 * Clones SilcBuffer. This generates new SilcBuffer and copies
1097 * everything from the source buffer. The result is exact clone of
1098 * the original buffer. Returns NULL if system is out of memory.
1100 * This routine use SilcStack are memory source. If `stack' is NULL
1101 * reverts back to normal allocating routine.
1103 * Note that this call consumes the `stack'. The caller should push the
1104 * stack before calling the function and pop it later.
1109 SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb)
1113 sb_new = silc_buffer_salloc_size(stack, silc_buffer_truelen(sb));
1114 if (silc_unlikely(!sb_new))
1116 silc_buffer_put(sb_new, sb->head, silc_buffer_truelen(sb));
1117 sb_new->data = sb_new->head + silc_buffer_headlen(sb);
1118 sb_new->tail = sb_new->data + silc_buffer_len(sb);
1123 /****f* silcutil/silc_buffer_realloc
1128 * SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize);
1132 * Reallocates buffer. Old data is saved into the new buffer. The buffer
1133 * is exact clone of the old one except that there is now more/less space
1134 * at the end of buffer. This always returns the same `sb' unless `sb'
1135 * was NULL. Returns NULL if system is out of memory.
1137 * If the `newsize' is shorter than the current buffer size, the data
1138 * and tail area of the buffer must be set to correct position before
1139 * calling this function so that buffer overflow would not occur when
1140 * the buffer size is reduced.
1145 SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize)
1147 SilcUInt32 hlen, dlen;
1151 return silc_buffer_alloc(newsize);
1153 if (silc_unlikely(newsize == silc_buffer_truelen(sb)))
1156 hlen = silc_buffer_headlen(sb);
1157 dlen = silc_buffer_len(sb);
1158 h = (unsigned char *)silc_realloc(sb->head, newsize);
1159 if (silc_unlikely(!h))
1162 sb->data = sb->head + hlen;
1163 sb->tail = sb->data + dlen;
1164 sb->end = sb->head + newsize;
1169 /****f* silcutil/silc_buffer_srealloc
1174 * SilcBuffer silc_buffer_srealloc(SilcStack stack,
1175 * SilcBuffer sb, SilcUInt32 newsize);
1179 * Reallocates buffer. Old data is saved into the new buffer. The buffer
1180 * is exact clone of the old one except that there is now more/less space
1181 * at the end of buffer. Returns NULL if system is out of memory. This
1182 * always returns `sb' unless `sb' was NULL.
1184 * If the `newsize' is shorter than the current buffer size, the data
1185 * and tail area of the buffer must be set to correct position before
1186 * calling this function so that buffer overflow would not occur when
1187 * the buffer size is reduced.
1189 * This routine use SilcStack are memory source. If `stack' is NULL
1190 * reverts back to normal allocating routine.
1192 * Note that this call consumes the `stack'. The caller should push the
1193 * stack before calling the function and pop it later.
1198 SilcBuffer silc_buffer_srealloc(SilcStack stack,
1199 SilcBuffer sb, SilcUInt32 newsize)
1201 SilcUInt32 hlen, dlen;
1205 return silc_buffer_realloc(sb, newsize);
1208 return silc_buffer_salloc(stack, newsize);
1210 if (newsize == silc_buffer_truelen(sb))
1213 hlen = silc_buffer_headlen(sb);
1214 dlen = silc_buffer_len(sb);
1215 h = (unsigned char *)silc_srealloc(stack, silc_buffer_truelen(sb),
1221 sb->data = sb->head + hlen;
1222 sb->tail = sb->data + dlen;
1223 sb->end = sb->head + newsize;
1228 /****f* silcutil/silc_buffer_realloc_size
1233 * SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize);
1237 * Same as silc_buffer_realloc but moves moves the tail area
1238 * automatically so that the buffer is ready to use without calling the
1239 * silc_buffer_pull_tail. Returns NULL if system is out of memory.
1244 SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize)
1246 sb = silc_buffer_realloc(sb, newsize);
1247 if (silc_unlikely(!sb))
1249 silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
1253 /****f* silcutil/silc_buffer_srealloc_size
1258 * SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1259 * SilcBuffer sb, SilcUInt32 newsize);
1263 * Same as silc_buffer_srealloc but moves moves the tail area
1264 * automatically so that the buffer is ready to use without calling the
1265 * silc_buffer_pull_tail. Returns NULL if system is out of memory.
1267 * This routine use SilcStack are memory source. If `stack' is NULL
1268 * reverts back to normal allocating routine.
1270 * Note that this call consumes the `stack'. The caller should push the
1271 * stack before calling the function and pop it later.
1276 SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1277 SilcBuffer sb, SilcUInt32 newsize)
1279 sb = silc_buffer_srealloc(stack, sb, newsize);
1280 if (silc_unlikely(!sb))
1282 silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
1286 /****f* silcutil/silc_buffer_enlarge
1291 * SilcBuffer silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size);
1295 * Enlarges the buffer by the amount of `size' if it doesn't have that
1296 * must space in the data area and in the tail area. Moves the tail
1297 * area automatically after enlarging so that the current data area
1298 * is at least the size of `size'. If there is more space than `size'
1299 * in the data area this does not do anything. If there is enough
1300 * space in the tail area this merely moves the tail area to reveal
1301 * the extra space. Returns FALSE if system is out of memory.
1306 SilcBool silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size)
1308 if (size > silc_buffer_len(sb)) {
1309 if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
1310 if (silc_unlikely(!silc_buffer_realloc(sb, silc_buffer_truelen(sb) +
1311 (size - silc_buffer_taillen(sb) -
1312 silc_buffer_len(sb)))))
1314 silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
1319 /****f* silcutil/silc_buffer_senlarge
1324 * SilcBuffer silc_buffer_senlarge(SilcStack stack, SilcBuffer sb,
1329 * Enlarges the buffer by the amount of `size' if it doesn't have that
1330 * must space in the data area and in the tail area. Moves the tail
1331 * area automatically after enlarging so that the current data area
1332 * is at least the size of `size'. If there is more space than `size'
1333 * in the data area this does not do anything. If there is enough
1334 * space in the tail area this merely moves the tail area to reveal
1335 * the extra space. Returns FALSE if system is out of memory.
1337 * This routine use SilcStack are memory source. If `stack' is NULL
1338 * reverts back to normal allocating routine.
1340 * Note that this call consumes the `stack'. The caller should push the
1341 * stack before calling the function and pop it later.
1346 SilcBool silc_buffer_senlarge(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
1348 if (size > silc_buffer_len(sb)) {
1349 if (size > silc_buffer_taillen(sb) + silc_buffer_len(sb))
1350 if (silc_unlikely(!silc_buffer_srealloc(stack, sb,
1351 silc_buffer_truelen(sb) +
1352 (size - silc_buffer_taillen(sb) -
1353 silc_buffer_len(sb)))))
1355 silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
1360 /****f* silcutil/silc_buffer_append
1365 * SilcBuffer silc_buffer_append(SilcBuffer sb, SilcUInt32 size);
1369 * Appends the current data area by the amount of `size'. The tail area
1370 * of the buffer remains intact and contains the same data than the old
1371 * tail area (the data is copied to the new tail area). After appending
1372 * there is now `size' bytes more free area in the data area. Returns
1373 * FALSE if system is out of memory.
1378 * ---------------------------------
1379 * | head | data | tail |
1380 * ---------------------------------
1383 * ------------------------------------
1384 * | head | data | tail |
1385 * -------------------------------------
1387 * silc_buffer_append(sb, 5);
1392 SilcBool silc_buffer_append(SilcBuffer sb, SilcUInt32 size)
1394 if (silc_unlikely(!silc_buffer_realloc(sb, silc_buffer_truelen(sb) + size)))
1397 /* Enlarge data area */
1398 silc_buffer_pull_tail(sb, size);
1400 /* Copy old tail area to new tail area */
1401 silc_buffer_put_tail(sb, sb->tail - size, silc_buffer_taillen(sb));
1406 /****f* silcutil/silc_buffer_sappend
1411 * SilcBool silc_buffer_sappend(SilcStack stack, SilcBuffer sb,
1416 * Appends the current data area by the amount of `size'. The tail area
1417 * of the buffer remains intact and contains the same data than the old
1418 * tail area (the data is copied to the new tail area). After appending
1419 * there is now `size' bytes more free area in the data area. Returns
1420 * FALSE if system is out of memory.
1422 * This routine use SilcStack are memory source. If `stack' is NULL
1423 * reverts back to normal allocating routine.
1425 * Note that this call consumes the `stack'. The caller should push the
1426 * stack before calling the function and pop it later.
1431 * ---------------------------------
1432 * | head | data | tail |
1433 * ---------------------------------
1436 * ------------------------------------
1437 * | head | data | tail |
1438 * -------------------------------------
1440 * silc_buffer_append(sb, 5);
1445 SilcBool silc_buffer_sappend(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
1447 if (silc_unlikely(!silc_buffer_srealloc(stack, sb,
1448 silc_buffer_truelen(sb) + size)))
1451 /* Enlarge data area */
1452 silc_buffer_pull_tail(sb, size);
1454 /* Copy old tail area to new tail area */
1455 silc_buffer_put_tail(sb, sb->tail - size, silc_buffer_taillen(sb));
1460 /****f* silcutil/silc_buffer_strchr
1465 * unsigned char *silc_buffer_strchr(SilcBuffer sb, int c, SilcBool first);
1469 * Returns pointer to the occurence of the character `c' in the buffer
1470 * `sb'. If the `first' is TRUE this finds the first occurene of `c',
1471 * if it is FALSE this finds the last occurence of `c'. If the character
1472 * is found the `sb' data area is moved to that location and its pointer
1473 * is returned. The silc_buffer_data call will return the same pointer.
1474 * Returns NULL if such character could not be located and the buffer
1475 * remains unmodified.
1477 * This call is equivalent to strchr(), strrchr(), memchr() and memrchr()
1478 * except it works with SilcBuffer.
1482 * This searches only the data area of the buffer. Head and tail area
1485 * The `sb' data need not be NULL terminated.
1490 unsigned char *silc_buffer_strchr(SilcBuffer sb, int c, SilcBool first)
1495 for (i = 0; i < silc_buffer_len(sb); i++) {
1496 if (sb->data[i] == (unsigned char)c) {
1497 sb->data = &sb->data[i];
1502 for (i = silc_buffer_len(sb) - 1; 1 >= 0; i--) {
1503 if (sb->data[i] == (unsigned char)c) {
1504 sb->data = &sb->data[i];
1513 /****f* silcutil/silc_buffer_equal
1518 * SilcBool silc_buffer_equal(SilcBuffer sb1, SilcBuffer sb2)
1522 * Compares if the data area of the buffer `sb1' and `sb2' are identical.
1523 * Returns TRUE if they match and FALSE if they differ.
1528 SilcBool silc_buffer_equal(SilcBuffer sb1, SilcBuffer sb2)
1530 if (silc_buffer_len(sb1) != silc_buffer_len(sb2))
1532 return memcmp(sb1->data, sb2->data, silc_buffer_len(sb1)) == 0;
1535 /****f* silcutil/silc_buffer_memcmp
1540 * SilcBool silc_buffer_memcmp(SilcBuffer buffer,
1541 * const unsigned char *data,
1542 * SilcUInt32 data_len)
1546 * Compares the data area of the buffer with the `data'. Returns TRUE
1547 * if the data area is identical to `data' or FALSE if they differ.
1552 SilcBool silc_buffer_memcmp(SilcBuffer buffer, const unsigned char *data,
1553 SilcUInt32 data_len)
1555 if (silc_buffer_len(buffer) != data_len)
1557 return memcmp(buffer->data, data, data_len) == 0;
1560 /****f* silcutil/silc_buffer_printf
1565 * void silc_buffer_printf(SilcBuffer sb, SilcBool newline);
1569 * Prints the current data area of `sb' into stdout. If `newline' is
1570 * TRUE prints '\n' after the data in the buffer.
1575 void silc_buffer_printf(SilcBuffer sb, SilcBool newline)
1577 silc_file_write(1, silc_buffer_data(sb), silc_buffer_len(sb));
1583 #endif /* SILCBUFFER_H */