SILC Runtime Toolkit 1.2 Beta 1
[runtime.git] / lib / silcutil / silcbuffer.h
1 /*
2
3   silcbuffer.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1998 - 2008 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 /****h* silcutil/Buffer Interface
21  *
22  * DESCRIPTION
23  *
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.
29  *
30  * The SilcBuffer context is not thread-safe and if same context must be
31  * used from multiple threads concurrency control must be employed.
32  *
33  ***/
34
35 #ifndef SILCBUFFER_H
36 #define SILCBUFFER_H
37
38 /****s* silcutil/SilcBuffer
39  *
40  * NAME
41  *
42  *    typedef struct { ... } *SilcBuffer, SilcBufferStruct;
43  *
44  * DESCRIPTION
45  *
46  *    SILC Buffer object. Following short description of the fields
47  *    of the buffer.
48  *
49  *     unsiged char *head;
50  *
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
55  *        pointer.
56  *
57  *        --------------------------------
58  *        | head  | data         | tail  |
59  *        --------------------------------
60  *        ^       ^
61  *
62  *        Current head section in the buffer is sb->data - sb->head.
63  *
64  *     unsigned char *data;
65  *
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.
68  *
69  *        --------------------------------
70  *        | head  | data         | tail  |
71  *        --------------------------------
72  *                ^              ^
73  *
74  *        Current valid data area in the buffer is sb->tail - sb->data.
75  *
76  *      unsigned char *tail;
77  *
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.
80  *
81  *        --------------------------------
82  *        | head  | data         | tail  |
83  *        --------------------------------
84  *                               ^       ^
85  *
86  *        Current tail section in the buffer is sb->end - sb->tail.
87  *
88  *     unsigned char *end;
89  *
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
93  *        of the buffer.
94  *
95  *        --------------------------------
96  *        | head  | data         | tail  |
97  *        --------------------------------
98  *                                       ^
99  *
100  *        Length of the entire buffer is (ie. truelen) sb->end - sb->head.
101  *
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.
109  *
110  * SOURCE
111  */
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;
118 /***/
119
120 /* Macros */
121
122 /****f* silcutil/silc_buffer_data
123  *
124  * NAME
125  *
126  *    unsigned char *silc_buffer_data(SilcBuffer sb)
127  *
128  * DESCRIPTION
129  *
130  *    Returns pointer to the data area of the buffer.
131  *
132  * SOURCE
133  */
134 #define silc_buffer_data(x) (x)->data
135 /***/
136
137 /****f* silcutil/silc_buffer_tail
138  *
139  * NAME
140  *
141  *    unsigned char *silc_buffer_tail(SilcBuffer sb)
142  *
143  * DESCRIPTION
144  *
145  *    Returns pointer to the tail area of the buffer.
146  *
147  * SOURCE
148  */
149 #define silc_buffer_tail(x) (x)->tail
150 /***/
151
152 /****f* silcutil/silc_buffer_datalen
153  *
154  * NAME
155  *
156  *    #define silc_buffer_datalen ...
157  *
158  * DESCRIPTION
159  *
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.
163  *
164  * EXAMPLE
165  *
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));
169  *
170  * SOURCE
171  */
172 #define silc_buffer_datalen(x) (x) ? silc_buffer_data((x)) : NULL, \
173   (x) ? silc_buffer_len((x)) : 0
174 /***/
175
176 /* Inline functions */
177
178 /****d* silcutil/silc_buffer_truelen
179  *
180  * NAME
181  *
182  *    SilcUInt32 silc_buffer_truelen(SilcBuffer sb)
183  *
184  * DESCRIPTION
185  *
186  *    Returns the true length of the buffer.
187  *
188  ***/
189 static inline
190 SilcUInt32 silc_buffer_truelen(SilcBuffer x)
191 {
192   return (SilcUInt32)(x->end - x->head);
193 }
194
195 /****d* silcutil/silc_buffer_len
196  *
197  * NAME
198  *
199  *    SilcUInt32 silc_buffer_len(SilcBuffer sb)
200  *
201  * DESCRIPTION
202  *
203  *    Returns the current length of the data area of the buffer.
204  *
205  ***/
206 static inline
207 SilcUInt32 silc_buffer_len(SilcBuffer x)
208 {
209   return (SilcUInt32)(x->tail - x->data);
210 }
211
212 /****d* silcutil/silc_buffer_headlen
213  *
214  * NAME
215  *
216  *    SilcUInt32 silc_buffer_headlen(SilcBuffer sb)
217  *
218  * DESCRIPTION
219  *
220  *    Returns the current length of the head data area of the buffer.
221  *
222  ***/
223 static inline
224 SilcUInt32 silc_buffer_headlen(SilcBuffer x)
225 {
226   return (SilcUInt32)(x->data - x->head);
227 }
228
229 /****d* silcutil/silc_buffer_taillen
230  *
231  * NAME
232  *
233  *    SilcUInt32 silc_buffer_taillen(SilcBuffer sb)
234  *
235  * DESCRIPTION
236  *
237  *    Returns the current length of the tail data area of the buffer.
238  *
239  ***/
240 static inline
241 SilcUInt32 silc_buffer_taillen(SilcBuffer x)
242 {
243   return (SilcUInt32)(x->end - x->tail);
244 }
245
246 /****f* silcutil/silc_buffer_alloc
247  *
248  * SYNOPSIS
249  *
250  *    static inline
251  *    SilcBuffer silc_buffer_alloc(SilcUInt32 len);
252  *
253  * DESCRIPTION
254  *
255  *    Allocates new SilcBuffer and returns it.  Returns NULL if system is
256  *    out of memory.
257  *
258  ***/
259
260 static inline
261 SilcBuffer silc_buffer_alloc(SilcUInt32 len)
262 {
263   SilcBuffer sb;
264
265   /* Allocate new SilcBuffer */
266   sb = (SilcBuffer)silc_calloc(1, sizeof(*sb));
267   if (silc_unlikely(!sb))
268     return NULL;
269
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))
274       return NULL;
275
276     /* Set pointers to the new buffer */
277     sb->data = sb->head;
278     sb->tail = sb->head;
279     sb->end = sb->head + len;
280   }
281
282   return sb;
283 }
284
285 /****f* silcutil/silc_buffer_salloc
286  *
287  * SYNOPSIS
288  *
289  *    static inline
290  *    SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len);
291  *
292  * DESCRIPTION
293  *
294  *    Allocates new SilcBuffer and returns it.  Returns NULL if system is
295  *    out of memory.
296  *
297  *    This routine use SilcStack are memory source.  If `stack' is NULL
298  *    reverts back to normal allocating routine.
299  *
300  *    Note that this call consumes the `stack'.  The caller should push the
301  *    stack before calling the function and pop it later.
302  *
303  ***/
304
305 static inline
306 SilcBuffer silc_buffer_salloc(SilcStack stack, SilcUInt32 len)
307 {
308   SilcBuffer sb;
309
310   if (!stack)
311     return silc_buffer_alloc(len);
312
313   /* Allocate new SilcBuffer */
314   sb = (SilcBuffer)silc_scalloc(stack, 1, sizeof(*sb));
315   if (silc_unlikely(!sb))
316     return NULL;
317
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))
322       return NULL;
323
324     /* Set pointers to the new buffer */
325     sb->data = sb->head;
326     sb->tail = sb->head;
327     sb->end = sb->head + len;
328   }
329
330   return sb;
331 }
332
333 /****f* silcutil/silc_buffer_free
334  *
335  * SYNOPSIS
336  *
337  *    static inline
338  *    void silc_buffer_free(SilcBuffer sb);
339  *
340  * DESCRIPTION
341  *
342  *    Frees SilcBuffer.  Can be called safely `sb' as NULL.
343  *
344  * NOTES
345  *
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.
349  *
350  ***/
351
352 static inline
353 void silc_buffer_free(SilcBuffer sb)
354 {
355   if (sb) {
356 #if defined(SILC_DEBUG)
357     if (sb->head)
358       memset(sb->head, 'F', silc_buffer_truelen(sb));
359 #endif
360     silc_free(sb->head);
361     silc_free(sb);
362   }
363 }
364
365 /****f* silcutil/silc_buffer_sfree
366  *
367  * SYNOPSIS
368  *
369  *    static inline
370  *    void silc_buffer_free(SilcStack stack, SilcBuffer sb);
371  *
372  * DESCRIPTION
373  *
374  *    Frees SilcBuffer.  If `stack' is NULL this calls silc_buffer_free.  Can
375  *    be called safely `sb' as NULL.
376  *
377  ***/
378
379 static inline
380 void silc_buffer_sfree(SilcStack stack, SilcBuffer sb)
381 {
382   if (stack) {
383 #ifdef SILC_DEBUG
384     if (sb) {
385       if (sb->head)
386         memset(sb->head, 'F', silc_buffer_truelen(sb));
387       memset(sb, 'F', sizeof(*sb));
388     }
389 #endif /* SILC_DEBUG */
390     return;
391   }
392
393   silc_buffer_free(sb);
394 }
395
396 /****f* silcutil/silc_buffer_steal
397  *
398  * SYNOPSIS
399  *
400  *    static inline
401  *    unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len);
402  *
403  * DESCRIPTION
404  *
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
410  *    silc_free.
411  *
412  ***/
413
414 static inline
415 unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
416 {
417   unsigned char *buf = sb->head;
418   if (data_len)
419     *data_len = silc_buffer_truelen(sb);
420   sb->head = sb->data = sb->tail = sb->end = NULL;
421   return buf;
422 }
423
424 /****f* silcutil/silc_buffer_purge
425  *
426  * SYNOPSIS
427  *
428  *    static inline
429  *    void silc_buffer_purge(SilcBuffer sb);
430  *
431  * DESCRIPTION
432  *
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.
436  *
437  * NOTES
438  *
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.
442  *
443  ***/
444
445 static inline
446 void silc_buffer_purge(SilcBuffer sb)
447 {
448   silc_free(silc_buffer_steal(sb, NULL));
449 }
450
451 /****f* silcutil/silc_buffer_spurge
452  *
453  * SYNOPSIS
454  *
455  *    static inline
456  *    void silc_buffer_spurge(SilcStack stack, SilcBuffer sb);
457  *
458  * DESCRIPTION
459  *
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.
464  *
465  ***/
466
467 static inline
468 void silc_buffer_spurge(SilcStack stack, SilcBuffer sb)
469 {
470   if (stack) {
471 #ifdef SILC_DEBUG
472     if (sb && sb->head)
473       memset(silc_buffer_steal(sb, NULL), 'F', silc_buffer_truelen(sb));
474 #endif /* SILC_DEBUG */
475     return;
476   }
477
478   silc_buffer_purge(sb);
479 }
480
481 /****f* silcutil/silc_buffer_set
482  *
483  * SYNOPSIS
484  *
485  *    static inline
486  *    void silc_buffer_set(SilcBuffer sb,
487  *                         unsigned char *data,
488  *                         SilcUInt32 data_len);
489  *
490  * DESCRIPTION
491  *
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.
496  *
497  * EXAMPLE
498  *
499  *    SilcBufferStruct buf;
500  *    silc_buffer_set(&buf, data, data_len);
501  *
502  ***/
503
504 static inline
505 void silc_buffer_set(SilcBuffer sb, unsigned char *data, SilcUInt32 data_len)
506 {
507   sb->data = sb->head = data;
508   sb->tail = sb->end = data + data_len;
509 }
510
511 /****f* silcutil/silc_buffer_pull
512  *
513  * SYNOPSIS
514  *
515  *    static inline
516  *    unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len);
517  *
518  * DESCRIPTION
519  *
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.
524  *
525  * EXAMPLE
526  *
527  *    ---------------------------------
528  *    | head  | data       | tail     |
529  *    ---------------------------------
530  *            ^
531  *            Pulls the start of the data area.
532  *
533  *    ---------------------------------
534  *    | head     | data    | tail     |
535  *    ---------------------------------
536  *            ^
537  *
538  *    silc_buffer_pull(sb, 20);
539  *
540  ***/
541
542 static inline
543 unsigned char *silc_buffer_pull(SilcBuffer sb, SilcUInt32 len)
544 {
545   unsigned char *old_data = sb->data;
546
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);
552     return NULL;
553   }
554
555   sb->data += len;
556   return old_data;
557 }
558
559 /****f* silcutil/silc_buffer_push
560  *
561  * SYNOPSIS
562  *
563  *    static inline
564  *    unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len);
565  *
566  * DESCRIPTION
567  *
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.
572  *
573  * EXAMPLE
574  *
575  *    ---------------------------------
576  *    | head     | data    | tail     |
577  *    ---------------------------------
578  *               ^
579  *               Pushes the start of the data area.
580  *
581  *    ---------------------------------
582  *    | head  | data       | tail     |
583  *    ---------------------------------
584  *               ^
585  *
586  *    silc_buffer_push(sb, 20);
587  *
588  ***/
589
590 static inline
591 unsigned char *silc_buffer_push(SilcBuffer sb, SilcUInt32 len)
592 {
593   unsigned char *old_data = sb->data;
594
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);
600     return NULL;
601   }
602
603   sb->data -= len;
604   return old_data;
605 }
606
607 /****f* silcutil/silc_buffer_pull_tail
608  *
609  * SYNOPSIS
610  *
611  *    static inline
612  *    unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len);
613  *
614  * DESCRIPTION
615  *
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.
619  *
620  * EXAMPLE
621  *
622  *    ---------------------------------
623  *    | head  | data       | tail     |
624  *    ---------------------------------
625  *                         ^
626  *                         Pulls the start of the tail section.
627  *
628  *    ---------------------------------
629  *    | head  | data           | tail |
630  *    ---------------------------------
631  *                         ^
632  *
633  *    silc_buffer_pull_tail(sb, 23);
634  *
635  ***/
636
637 static inline
638 unsigned char *silc_buffer_pull_tail(SilcBuffer sb, SilcUInt32 len)
639 {
640   unsigned char *old_tail = sb->tail;
641
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);
647     return NULL;
648   }
649
650   sb->tail += len;
651   return old_tail;
652 }
653
654 /****f* silcutil/silc_buffer_push_tail
655  *
656  * SYNOPSIS
657  *
658  *    static inline
659  *    unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len);
660  *
661  * DESCRIPTION
662  *
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.
667  *
668  * EXAMPLE
669  *
670  *    ---------------------------------
671  *    | head  | data           | tail |
672  *    ---------------------------------
673  *                             ^
674  *                             Pushes the start of the tail section.
675  *
676  *    ---------------------------------
677  *    | head  | data       | tail     |
678  *    ---------------------------------
679  *                             ^
680  *
681  *    silc_buffer_push_tail(sb, 23);
682  *
683  ***/
684
685 static inline
686 unsigned char *silc_buffer_push_tail(SilcBuffer sb, SilcUInt32 len)
687 {
688   unsigned char *old_tail = sb->tail;
689
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);
695     return NULL;
696   }
697
698   sb->tail -= len;
699   return old_tail;
700 }
701
702 /****f* silcutil/silc_buffer_put_head
703  *
704  * SYNOPSIS
705  *
706  *    static inline
707  *    unsigned char *silc_buffer_put_head(SilcBuffer sb,
708  *                                        const unsigned char *data,
709  *                                        SilcUInt32 len);
710  *
711  * DESCRIPTION
712  *
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
715  *    area.
716  *
717  * EXAMPLE
718  *
719  *    ---------------------------------
720  *    | head  | data       | tail     |
721  *    ---------------------------------
722  *    ^
723  *    Puts data to the head section.
724  *
725  *    silc_buffer_put_head(sb, data, data_len);
726  *
727  ***/
728
729 static inline
730 unsigned char *silc_buffer_put_head(SilcBuffer sb,
731                                     const unsigned char *data,
732                                     SilcUInt32 len)
733 {
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);
739     return NULL;
740   }
741
742   if (sb->head > data) {
743     if (sb->head - data <= len)
744       return (unsigned char *)memmove(sb->head, data, len);
745   } else {
746     if (data - sb->head <= len)
747       return (unsigned char *)memmove(sb->head, data, len);
748   }
749
750   return (unsigned char *)memcpy(sb->head, data, len);
751 }
752
753 /****f* silcutil/silc_buffer_put
754  *
755  * SYNOPSIS
756  *
757  *    static inline
758  *    unsigned char *silc_buffer_put(SilcBuffer sb,
759  *                                   const unsigned char *data,
760  *                                   SilcUInt32 len);
761  *
762  * DESCRIPTION
763  *
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
766  *    current data area.
767  *
768  * EXAMPLE
769  *
770  *    ---------------------------------
771  *    | head  | data       | tail     |
772  *    ---------------------------------
773  *            ^
774  *            Puts data to the data section.
775  *
776  *    silc_buffer_put(sb, data, data_len);
777  *
778  ***/
779
780 static inline
781 unsigned char *silc_buffer_put(SilcBuffer sb,
782                                const unsigned char *data,
783                                SilcUInt32 len)
784 {
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);
790     return NULL;
791   }
792
793   if (sb->data > data) {
794     if (sb->data - data <= len)
795       return (unsigned char *)memmove(sb->data, data, len);
796   } else {
797     if (data - sb->data <= len)
798       return (unsigned char *)memmove(sb->data, data, len);
799   }
800
801   return (unsigned char *)memcpy(sb->data, data, len);
802 }
803
804 /****f* silcutil/silc_buffer_put_tail
805  *
806  * SYNOPSIS
807  *
808  *    static inline
809  *    unsigned char *silc_buffer_put_tail(SilcBuffer sb,
810  *                                        const unsigned char *data,
811  *                                        SilcUInt32 len);
812  *
813  * DESCRIPTION
814  *
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
817  *    area.
818  *
819  * EXAMPLE
820  *
821  *    ---------------------------------
822  *    | head  | data           | tail |
823  *    ---------------------------------
824  *                             ^
825  *                             Puts data to the tail section.
826  *
827  *    silc_buffer_put_tail(sb, data, data_len);
828  *
829  ***/
830
831 static inline
832 unsigned char *silc_buffer_put_tail(SilcBuffer sb,
833                                     const unsigned char *data,
834                                     SilcUInt32 len)
835 {
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);
841     return NULL;
842   }
843
844   if (sb->tail > data) {
845     if (sb->tail - data <= len)
846       return (unsigned char *)memmove(sb->tail, data, len);
847   } else {
848     if (data - sb->tail <= len)
849       return (unsigned char *)memmove(sb->tail, data, len);
850   }
851
852   return (unsigned char *)memcpy(sb->tail, data, len);
853 }
854
855 /****f* silcutil/silc_buffer_alloc_size
856  *
857  * SYNOPSIS
858  *
859  *    static inline
860  *    SilcBuffer silc_buffer_alloc_size(SilcUInt32 len);
861  *
862  * DESCRIPTION
863  *
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.
867  *
868  ***/
869
870 static inline
871 SilcBuffer silc_buffer_alloc_size(SilcUInt32 len)
872 {
873   SilcBuffer sb = silc_buffer_alloc(len);
874   if (silc_unlikely(!sb))
875     return NULL;
876   silc_buffer_pull_tail(sb, len);
877   return sb;
878 }
879
880 /****f* silcutil/silc_buffer_salloc_size
881  *
882  * SYNOPSIS
883  *
884  *    static inline
885  *    SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len);
886  *
887  * DESCRIPTION
888  *
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.
892  *
893  *    This routine use SilcStack are memory source.  If `stack' is NULL
894  *    reverts back to normal allocating routine.
895  *
896  *    Note that this call consumes the `stack'.  The caller should push the
897  *    stack before calling the function and pop it later.
898  *
899  ***/
900
901 static inline
902 SilcBuffer silc_buffer_salloc_size(SilcStack stack, SilcUInt32 len)
903 {
904   SilcBuffer sb = silc_buffer_salloc(stack, len);
905   if (silc_unlikely(!sb))
906     return NULL;
907   silc_buffer_pull_tail(sb, len);
908   return sb;
909 }
910
911 /****f* silcutil/silc_buffer_reset
912  *
913  * SYNOPSIS
914  *
915  *    static inline
916  *    void silc_buffer_reset(SilcBuffer sb);
917  *
918  * DESCRIPTION
919  *
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.
923  *
924  ***/
925
926 static inline
927 void silc_buffer_reset(SilcBuffer sb)
928 {
929   sb->data = sb->tail = sb->head;
930 }
931
932 /****f* silcutil/silc_buffer_clear
933  *
934  * SYNOPSIS
935  *
936  *    static inline
937  *    void silc_buffer_clear(SilcBuffer sb);
938  *
939  * DESCRIPTION
940  *
941  *    Clears and initialiazes the buffer to the state as if it was just
942  *    allocated by silc_buffer_alloc.
943  *
944  ***/
945
946 static inline
947 void silc_buffer_clear(SilcBuffer sb)
948 {
949   memset(sb->head, 0, silc_buffer_truelen(sb));
950   silc_buffer_reset(sb);
951 }
952
953 /****f* silcutil/silc_buffer_start
954  *
955  * SYNOPSIS
956  *
957  *    static inline
958  *    void silc_buffer_start(SilcBuffer sb);
959  *
960  * DESCRIPTION
961  *
962  *    Moves the data area at the start of the buffer.  The tail area remains
963  *    as is.
964  *
965  ***/
966
967 static inline
968 void silc_buffer_start(SilcBuffer sb)
969 {
970   sb->data = sb->head;
971 }
972
973 /****f* silcutil/silc_buffer_end
974  *
975  * SYNOPSIS
976  *
977  *    static inline
978  *    void silc_buffer_end(SilcBuffer sb);
979  *
980  * DESCRIPTION
981  *
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.
986  *
987  ***/
988
989 static inline
990 void silc_buffer_end(SilcBuffer sb)
991 {
992   sb->tail = sb->end;
993 }
994
995 /****f* silcutil/silc_buffer_copy
996  *
997  * SYNOPSIS
998  *
999  *    static inline
1000  *    SilcBuffer silc_buffer_copy(SilcBuffer sb);
1001  *
1002  * DESCRIPTION
1003  *
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.
1007  *
1008  ***/
1009
1010 static inline
1011 SilcBuffer silc_buffer_copy(SilcBuffer sb)
1012 {
1013   SilcBuffer sb_new;
1014
1015   sb_new = silc_buffer_alloc_size(silc_buffer_len(sb));
1016   if (silc_unlikely(!sb_new))
1017     return NULL;
1018   silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
1019
1020   return sb_new;
1021 }
1022
1023 /****f* silcutil/silc_buffer_scopy
1024  *
1025  * SYNOPSIS
1026  *
1027  *    static inline
1028  *    SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb);
1029  *
1030  * DESCRIPTION
1031  *
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.
1035  *
1036  *    This routine use SilcStack are memory source.  If `stack' is NULL
1037  *    reverts back to normal allocating routine.
1038  *
1039  *    Note that this call consumes the `stack'.  The caller should push the
1040  *    stack before calling the function and pop it later.
1041  *
1042  ***/
1043
1044 static inline
1045 SilcBuffer silc_buffer_scopy(SilcStack stack, SilcBuffer sb)
1046 {
1047   SilcBuffer sb_new;
1048
1049   sb_new = silc_buffer_salloc_size(stack, silc_buffer_len(sb));
1050   if (silc_unlikely(!sb_new))
1051     return NULL;
1052   silc_buffer_put(sb_new, sb->data, silc_buffer_len(sb));
1053
1054   return sb_new;
1055 }
1056
1057 /****f* silcutil/silc_buffer_clone
1058  *
1059  * SYNOPSIS
1060  *
1061  *    static inline
1062  *    SilcBuffer silc_buffer_clone(SilcBuffer sb);
1063  *
1064  * DESCRIPTION
1065  *
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.
1069  *
1070  ***/
1071
1072 static inline
1073 SilcBuffer silc_buffer_clone(SilcBuffer sb)
1074 {
1075   SilcBuffer sb_new;
1076
1077   sb_new = silc_buffer_alloc_size(silc_buffer_truelen(sb));
1078   if (silc_unlikely(!sb_new))
1079     return NULL;
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);
1083
1084   return sb_new;
1085 }
1086
1087 /****f* silcutil/silc_buffer_sclone
1088  *
1089  * SYNOPSIS
1090  *
1091  *    static inline
1092  *    SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb);
1093  *
1094  * DESCRIPTION
1095  *
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.
1099  *
1100  *    This routine use SilcStack are memory source.  If `stack' is NULL
1101  *    reverts back to normal allocating routine.
1102  *
1103  *    Note that this call consumes the `stack'.  The caller should push the
1104  *    stack before calling the function and pop it later.
1105  *
1106  ***/
1107
1108 static inline
1109 SilcBuffer silc_buffer_sclone(SilcStack stack, SilcBuffer sb)
1110 {
1111   SilcBuffer sb_new;
1112
1113   sb_new = silc_buffer_salloc_size(stack, silc_buffer_truelen(sb));
1114   if (silc_unlikely(!sb_new))
1115     return NULL;
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);
1119
1120   return sb_new;
1121 }
1122
1123 /****f* silcutil/silc_buffer_realloc
1124  *
1125  * SYNOPSIS
1126  *
1127  *    static inline
1128  *    SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize);
1129  *
1130  * DESCRIPTION
1131  *
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.
1136  *
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.
1141  *
1142  ***/
1143
1144 static inline
1145 SilcBuffer silc_buffer_realloc(SilcBuffer sb, SilcUInt32 newsize)
1146 {
1147   SilcUInt32 hlen, dlen;
1148   unsigned char *h;
1149
1150   if (!sb)
1151     return silc_buffer_alloc(newsize);
1152
1153   if (silc_unlikely(newsize == silc_buffer_truelen(sb)))
1154     return sb;
1155
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))
1160     return NULL;
1161   sb->head = h;
1162   sb->data = sb->head + hlen;
1163   sb->tail = sb->data + dlen;
1164   sb->end = sb->head + newsize;
1165
1166   return sb;
1167 }
1168
1169 /****f* silcutil/silc_buffer_srealloc
1170  *
1171  * SYNOPSIS
1172  *
1173  *    static inline
1174  *    SilcBuffer silc_buffer_srealloc(SilcStack stack,
1175  *                                    SilcBuffer sb, SilcUInt32 newsize);
1176  *
1177  * DESCRIPTION
1178  *
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.
1183  *
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.
1188  *
1189  *    This routine use SilcStack are memory source.  If `stack' is NULL
1190  *    reverts back to normal allocating routine.
1191  *
1192  *    Note that this call consumes the `stack'.  The caller should push the
1193  *    stack before calling the function and pop it later.
1194  *
1195  ***/
1196
1197 static inline
1198 SilcBuffer silc_buffer_srealloc(SilcStack stack,
1199                                 SilcBuffer sb, SilcUInt32 newsize)
1200 {
1201   SilcUInt32 hlen, dlen;
1202   unsigned char *h;
1203
1204   if (!stack)
1205     return silc_buffer_realloc(sb, newsize);
1206
1207   if (!sb)
1208     return silc_buffer_salloc(stack, newsize);
1209
1210   if (newsize == silc_buffer_truelen(sb))
1211     return sb;
1212
1213   hlen = silc_buffer_headlen(sb);
1214   dlen = silc_buffer_len(sb);
1215   h = (unsigned char *)silc_srealloc(stack, silc_buffer_truelen(sb),
1216                                      sb->head, newsize);
1217   if (!h)
1218     return NULL;
1219
1220   sb->head = h;
1221   sb->data = sb->head + hlen;
1222   sb->tail = sb->data + dlen;
1223   sb->end = sb->head + newsize;
1224
1225   return sb;
1226 }
1227
1228 /****f* silcutil/silc_buffer_realloc_size
1229  *
1230  * SYNOPSIS
1231  *
1232  *    static inline
1233  *    SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize);
1234  *
1235  * DESCRIPTION
1236  *
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.
1240  *
1241  ***/
1242
1243 static inline
1244 SilcBuffer silc_buffer_realloc_size(SilcBuffer sb, SilcUInt32 newsize)
1245 {
1246   sb = silc_buffer_realloc(sb, newsize);
1247   if (silc_unlikely(!sb))
1248     return NULL;
1249   silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
1250   return sb;
1251 }
1252
1253 /****f* silcutil/silc_buffer_srealloc_size
1254  *
1255  * SYNOPSIS
1256  *
1257  *    static inline
1258  *    SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1259  *                                         SilcBuffer sb, SilcUInt32 newsize);
1260  *
1261  * DESCRIPTION
1262  *
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.
1266  *
1267  *    This routine use SilcStack are memory source.  If `stack' is NULL
1268  *    reverts back to normal allocating routine.
1269  *
1270  *    Note that this call consumes the `stack'.  The caller should push the
1271  *    stack before calling the function and pop it later.
1272  *
1273  ***/
1274
1275 static inline
1276 SilcBuffer silc_buffer_srealloc_size(SilcStack stack,
1277                                      SilcBuffer sb, SilcUInt32 newsize)
1278 {
1279   sb = silc_buffer_srealloc(stack, sb, newsize);
1280   if (silc_unlikely(!sb))
1281     return NULL;
1282   silc_buffer_pull_tail(sb, silc_buffer_taillen(sb));
1283   return sb;
1284 }
1285
1286 /****f* silcutil/silc_buffer_enlarge
1287  *
1288  * SYNOPSIS
1289  *
1290  *    static inline
1291  *    SilcBuffer silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size);
1292  *
1293  * DESCRIPTION
1294  *
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.
1302  *
1303  ***/
1304
1305 static inline
1306 SilcBool silc_buffer_enlarge(SilcBuffer sb, SilcUInt32 size)
1307 {
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)))))
1313         return FALSE;
1314     silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
1315   }
1316   return TRUE;
1317 }
1318
1319 /****f* silcutil/silc_buffer_senlarge
1320  *
1321  * SYNOPSIS
1322  *
1323  *    static inline
1324  *    SilcBuffer silc_buffer_senlarge(SilcStack stack, SilcBuffer sb,
1325  *                                    SilcUInt32 size);
1326  *
1327  * DESCRIPTION
1328  *
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.
1336  *
1337  *    This routine use SilcStack are memory source.  If `stack' is NULL
1338  *    reverts back to normal allocating routine.
1339  *
1340  *    Note that this call consumes the `stack'.  The caller should push the
1341  *    stack before calling the function and pop it later.
1342  *
1343  ***/
1344
1345 static inline
1346 SilcBool silc_buffer_senlarge(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
1347 {
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)))))
1354         return FALSE;
1355     silc_buffer_pull_tail(sb, size - silc_buffer_len(sb));
1356   }
1357   return TRUE;
1358 }
1359
1360 /****f* silcutil/silc_buffer_append
1361  *
1362  * SYNOPSIS
1363  *
1364  *    static inline
1365  *    SilcBuffer silc_buffer_append(SilcBuffer sb, SilcUInt32 size);
1366  *
1367  * DESCRIPTION
1368  *
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.
1374  *
1375  * EXAMPLE
1376  *
1377  *    Before appending:
1378  *    ---------------------------------
1379  *    | head  | data           | tail |
1380  *    ---------------------------------
1381  *
1382  *    After appending:
1383  *    ------------------------------------
1384  *    | head  | data               | tail |
1385  *    -------------------------------------
1386  *
1387  *    silc_buffer_append(sb, 5);
1388  *
1389  ***/
1390
1391 static inline
1392 SilcBool silc_buffer_append(SilcBuffer sb, SilcUInt32 size)
1393 {
1394   if (silc_unlikely(!silc_buffer_realloc(sb, silc_buffer_truelen(sb) + size)))
1395     return FALSE;
1396
1397   /* Enlarge data area */
1398   silc_buffer_pull_tail(sb, size);
1399
1400   /* Copy old tail area to new tail area */
1401   silc_buffer_put_tail(sb, sb->tail - size, silc_buffer_taillen(sb));
1402
1403   return TRUE;
1404 }
1405
1406 /****f* silcutil/silc_buffer_sappend
1407  *
1408  * SYNOPSIS
1409  *
1410  *    static inline
1411  *    SilcBool silc_buffer_sappend(SilcStack stack, SilcBuffer sb,
1412  *                                 SilcUInt32 size)
1413  *
1414  * DESCRIPTION
1415  *
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.
1421  *
1422  *    This routine use SilcStack are memory source.  If `stack' is NULL
1423  *    reverts back to normal allocating routine.
1424  *
1425  *    Note that this call consumes the `stack'.  The caller should push the
1426  *    stack before calling the function and pop it later.
1427  *
1428  * EXAMPLE
1429  *
1430  *    Before appending:
1431  *    ---------------------------------
1432  *    | head  | data           | tail |
1433  *    ---------------------------------
1434  *
1435  *    After appending:
1436  *    ------------------------------------
1437  *    | head  | data               | tail |
1438  *    -------------------------------------
1439  *
1440  *    silc_buffer_append(sb, 5);
1441  *
1442  ***/
1443
1444 static inline
1445 SilcBool silc_buffer_sappend(SilcStack stack, SilcBuffer sb, SilcUInt32 size)
1446 {
1447   if (silc_unlikely(!silc_buffer_srealloc(stack, sb,
1448                                           silc_buffer_truelen(sb) + size)))
1449     return FALSE;
1450
1451   /* Enlarge data area */
1452   silc_buffer_pull_tail(sb, size);
1453
1454   /* Copy old tail area to new tail area */
1455   silc_buffer_put_tail(sb, sb->tail - size, silc_buffer_taillen(sb));
1456
1457   return TRUE;
1458 }
1459
1460 /****f* silcutil/silc_buffer_strchr
1461  *
1462  * SYNOPSIS
1463  *
1464  *    static inline
1465  *    unsigned char *silc_buffer_strchr(SilcBuffer sb, int c, SilcBool first);
1466  *
1467  * DESCRIPTION
1468  *
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.
1476  *
1477  *    This call is equivalent to strchr(), strrchr(), memchr() and memrchr()
1478  *    except it works with SilcBuffer.
1479  *
1480  * NOTES
1481  *
1482  *    This searches only the data area of the buffer.  Head and tail area
1483  *    are not searched.
1484  *
1485  *    The `sb' data need not be NULL terminated.
1486  *
1487  ***/
1488
1489 static inline
1490 unsigned char *silc_buffer_strchr(SilcBuffer sb, int c, SilcBool first)
1491 {
1492   int i;
1493
1494   if (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];
1498         return sb->data;
1499       }
1500     }
1501   } else {
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];
1505         return sb->data;
1506       }
1507     }
1508   }
1509
1510   return NULL;
1511 }
1512
1513 /****f* silcutil/silc_buffer_equal
1514  *
1515  * SYNOPSIS
1516  *
1517  *    static inline
1518  *    SilcBool silc_buffer_equal(SilcBuffer sb1, SilcBuffer sb2)
1519  *
1520  * DESCRIPTION
1521  *
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.
1524  *
1525  ***/
1526
1527 static inline
1528 SilcBool silc_buffer_equal(SilcBuffer sb1, SilcBuffer sb2)
1529 {
1530   if (silc_buffer_len(sb1) != silc_buffer_len(sb2))
1531     return FALSE;
1532   return memcmp(sb1->data, sb2->data, silc_buffer_len(sb1)) == 0;
1533 }
1534
1535 /****f* silcutil/silc_buffer_memcmp
1536  *
1537  * SYNOPSIS
1538  *
1539  *    static inline
1540  *    SilcBool silc_buffer_memcmp(SilcBuffer buffer,
1541  *                                const unsigned char *data,
1542  *                                SilcUInt32 data_len)
1543  *
1544  * DESCRIPTION
1545  *
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.
1548  *
1549  ***/
1550
1551 static inline
1552 SilcBool silc_buffer_memcmp(SilcBuffer buffer, const unsigned char *data,
1553                             SilcUInt32 data_len)
1554 {
1555   if (silc_buffer_len(buffer) != data_len)
1556     return FALSE;
1557   return memcmp(buffer->data, data, data_len) == 0;
1558 }
1559
1560 /****f* silcutil/silc_buffer_printf
1561  *
1562  * SYNOPSIS
1563  *
1564  *    static inline
1565  *    void silc_buffer_printf(SilcBuffer sb, SilcBool newline);
1566  *
1567  * DESCRIPTION
1568  *
1569  *    Prints the current data area of `sb' into stdout.  If `newline' is
1570  *    TRUE prints '\n' after the data in the buffer.
1571  *
1572  ***/
1573
1574 static inline
1575 void silc_buffer_printf(SilcBuffer sb, SilcBool newline)
1576 {
1577   silc_file_write(1, silc_buffer_data(sb), silc_buffer_len(sb));
1578   if (newline)
1579     printf("\n");
1580   fflush(stdout);
1581 }
1582
1583 #endif /* SILCBUFFER_H */