Added SilcStack aware buffer unformatting.
[crypto.git] / lib / silcutil / silcbuffmt.h
1 /*
2
3   silcbuffmt.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 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/SILC Buffer Format Interface
21  *
22  * DESCRIPTION
23  *
24  * SILC Buffer Format API provides functions for formatting different data
25  * types into a buffer and retrieving different data types from a buffer
26  * into specified data types.  It is especially useful to format packets,
27  * protocol payloads and such.
28  *
29  * As the SilcBuffer API is not thread-safe these routines may not be used
30  * in multithreaded environment with a same SilcBuffer context without
31  * concurrency control.
32  *
33  ***/
34
35 #ifndef SILCBUFFMT_H
36 #define SILCBUFFMT_H
37
38 /* Prototypes */
39
40 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format
41  *
42  * SYNOPSIS
43  *
44  *    int silc_buffer_format(SilcBuffer dst, ...);
45  *
46  * DESCRIPTION
47  *
48  *    Formats a buffer from a variable argument list.  Returns -1 on error
49  *    and the length of the formatted buffer otherwise.  The buffer is
50  *    enlarged automatically during formatting, if it doesn't already have
51  *    enough space.
52  *
53  * EXAMPLE
54  *
55  *    SilcBufferStruct buffer;
56  *    SilcBuffer buf;
57  *
58  *    memset(&buffer, 0, sizeof(buffer));
59  *    ret = silc_buffer_format(&buffer,
60  *                             SILC_STR_INT(intval),
61  *                             SILC_STR_CHAR(charval),
62  *                             SILC_STR_INT(intval),
63  *                             SILC_STR_SHORT(str_len),
64  *                             SILC_STR_UI_XNSTRING(str, str_len),
65  *                             SILC_STR_END);
66  *    if (ret < 0)
67  *      error;
68  *
69  *    // Free the allocated data
70  *    silc_buffer_purge(&buffer);
71  *
72  *    // Allocate zero size buffer
73  *    buf = silc_buffer_alloc(0);
74  *    ret = silc_buffer_format(buf,
75  *                             SILC_STR_INT(intval),
76  *                             SILC_STR_CHAR(charval),
77  *                             SILC_STR_END);
78  *
79  *    // Free the allocated buffer
80  *    silc_buffer_free(buf);
81  *
82  ***/
83 int silc_buffer_format(SilcBuffer dst, ...);
84
85 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat
86  *
87  * SYNOPSIS
88  *
89  *    int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
90  *
91  * DESCRIPTION
92  *
93  *    Same as silc_buffer_format but uses `stack' to allocate the memory.
94  *    if `stack' is NULL reverts back to silc_buffer_format call.
95  *
96  ***/
97 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
98
99 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
100  *
101  * SYNOPSIS
102  *
103  *    int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
104  *
105  * DESCRIPTION
106  *
107  *    Formats a buffer from a variable argument list indicated by the `ap'.
108  *    Returns -1 on error and the length of the formatted buffer otherwise.
109  *
110  ***/
111 int silc_buffer_format_vp(SilcBuffer dst, va_list ap);
112
113 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
114  *
115  * SYNOPSIS
116  *
117  *    int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
118  *
119  * DESCRIPTION
120  *
121  *    Same as silc_buffer_format_vp but uses `stack' to allocate the memory.
122  *    if `stack' is NULL reverts back to silc_buffer_format_vp call.
123  *
124  ***/
125 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap);
126
127 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat
128  *
129  * SYNOPSIS
130  *
131  *    int silc_buffer_unformat(SilcBuffer src, ...);
132  *
133  * DESCRIPTION
134  *
135  *    Unformats a buffer from a variable argument list.  Returns -1 on error
136  *    and the length of the unformatted buffer otherwise.
137  *
138  * EXAMPLE
139  *
140  *    ret = silc_buffer_unformat(buffer,
141  *                               SILC_STR_INT(&intval),
142  *                               SILC_STR_CHAR(&charval),
143  *                               SILC_STR_OFFSET(4),
144  *                               SILC_STR_UI16_NSTRING_ALLOC(&str, &str_len),
145  *                               SILC_STR_END);
146  *    if (ret < 0)
147  *      error;
148  *
149  ***/
150 int silc_buffer_unformat(SilcBuffer src, ...);
151
152 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat
153  *
154  * SYNOPSIS
155  *
156  *    int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...);
157  *
158  * DESCRIPTION
159  *
160  *    Same as silc_buffer_unformat but uses `stack' to allocate the memory.
161  *    if `stack' is NULL reverts back to silc_buffer_format call.
162  *
163  ***/
164 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...);
165
166 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat_vp
167  *
168  * SYNOPSIS
169  *
170  *    int silc_buffer_unformat_vp(SilcBuffer src, va_list vp);
171  *
172  * DESCRIPTION
173  *
174  *    Unformats a buffer from a variable argument list indicated by the `ap'.
175  *    Returns -1 on error and the length of the unformatted buffer otherwise.
176  *
177  ***/
178 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap);
179
180 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat_vp
181  *
182  * SYNOPSIS
183  *
184  *    int silc_buffer_sunformat_vp(SilcBuffer src, va_list vp);
185  *
186  * DESCRIPTION
187  *
188  *    Same as silc_buffer_unformat_vp but uses `stack' to allocate the
189  *    memory.  if `stack' is NULL reverts back to silc_buffer_format_vp call.
190  *
191  ***/
192 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap);
193
194 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_strformat
195  *
196  * SYNOPSIS
197  *
198  *   int silc_buffer_strformat(SilcBuffer dst, ...);
199  *
200  * DESCRIPTION
201  *
202  *   Formats a buffer from variable argument list of strings.  Each
203  *   string must be NULL-terminated and the variable argument list must
204  *   be end with SILC_STR_END argument.  This allows that a string in
205  *   the list can be NULL, in which case it is skipped.  This automatically
206  *   allocates the space for the buffer data but `dst' must be already
207  *   allocated by the caller.
208  *
209  * EXAMPLE
210  *
211  *    ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STRFMT_END);
212  *    if (ret < 0)
213  *      error;
214  *
215  ***/
216 int silc_buffer_strformat(SilcBuffer dst, ...);
217
218 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sstrformat
219  *
220  * SYNOPSIS
221  *
222  *   int silc_buffer_strformat(SilcStack stack, SilcBuffer dst, ...);
223  *
224  * DESCRIPTION
225  *
226  *   Formats a buffer from variable argument list of strings.  Each
227  *   string must be NULL-terminated and the variable argument list must
228  *   be end with SILC_STR_END argument.  This allows that a string in
229  *   the list can be NULL, in which case it is skipped.  This automatically
230  *   allocates the space for the buffer data but `dst' must be already
231  *   allocated by the caller.  This function is equivalent to
232  *   silc_buffer_strformat but allocates memory from `stack'.
233  *
234  ***/
235 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...);
236
237 /****d* silcutil/SilcBufferFormatAPI/SilcBufferParamType
238  *
239  * NAME
240  *
241  *    typedef enum { ... } SilcBufferParamType;
242  *
243  * DESCRIPTION
244  *
245  *    Buffer parameter types.  These are not needed when formatting or
246  *    unformatting buffers.  Use the macros such as SILC_STR_UI_CHAR and
247  *    others instead.  These types may be used when describing what a
248  *    buffer looks like, and how it may be formatted and unformatted.
249  *
250  * SOURCE
251  */
252 typedef enum {
253   SILC_PARAM_SI8_CHAR,             /* Signed 8-bit char */
254   SILC_PARAM_UI8_CHAR,             /* Unsigned 8-bit char */
255   SILC_PARAM_SI16_SHORT,           /* Signed 16-bit int */
256   SILC_PARAM_UI16_SHORT,           /* Unsigned 16-bit int */
257   SILC_PARAM_SI32_INT,             /* Signed 32-bit int */
258   SILC_PARAM_UI32_INT,             /* Unsigned 32-bit int */
259   SILC_PARAM_SI64_INT,             /* Signed 64-bit int */
260   SILC_PARAM_UI64_INT,             /* Unsigned 64-bit int */
261   SILC_PARAM_UI8_STRING,           /* String (max len 8-bits)*/
262   SILC_PARAM_UI16_STRING,          /* String (max len 16-bits) */
263   SILC_PARAM_UI32_STRING,          /* String (max len 32-bits) */
264   SILC_PARAM_BUFFER,               /* SilcBuffer */
265
266   /* Internal types */
267   SILC_PARAM_DATA,                 /* Binary data */
268   SILC_PARAM_UI8_NSTRING,          /* String (max len 8-bits) */
269   SILC_PARAM_UI16_NSTRING,         /* String (max len 16-bits) */
270   SILC_PARAM_UI32_NSTRING,         /* String (max len 32-bits) */
271   SILC_PARAM_UI8_STRING_ALLOC,     /* Alloc + memcpy */
272   SILC_PARAM_UI16_STRING_ALLOC,    /* Alloc + memcpy */
273   SILC_PARAM_UI32_STRING_ALLOC,    /* Alloc + memcpy */
274   SILC_PARAM_UI8_NSTRING_ALLOC,    /* Alloc + memcpy */
275   SILC_PARAM_UI16_NSTRING_ALLOC,   /* Alloc + memcpy */
276   SILC_PARAM_UI32_NSTRING_ALLOC,   /* Alloc + memcpy */
277   SILC_PARAM_DATA_ALLOC,           /* Alloc + memcpy */
278   SILC_PARAM_BUFFER_ALLOC,         /* Alloc + memcpy */
279
280   SILC_PARAM_OFFSET,
281   SILC_PARAM_ADVANCE,
282
283   SILC_PARAM_UI_XNSTRING,
284   SILC_PARAM_UI_XNSTRING_ALLOC,
285
286   SILC_PARAM_END
287 } SilcBufferParamType;
288 /***/
289
290 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_CHAR
291  *
292  * NAME
293  *
294  *    #define SILC_STR_UI_CHAR() ...
295  *    #define SILC_STR_SI_CHAR() ...
296  *
297  * DESCRIPTION
298  *
299  *    One signed/unsigned character.
300  *
301  *    Formatting:    SILC_STR_SI_CHAR(char)
302  *                   SILC_STR_UI_CHAR(unsigned char)
303  *    Unformatting:  SILC_STR_SI_CHAR(char *)
304  *                   SILC_STR_UI_CHAR(unsigned char *)
305  *
306  ***/
307 #define SILC_STR_SI_CHAR(x) SILC_PARAM_SI8_CHAR, (x)
308 #define SILC_STR_UI_CHAR(x) SILC_PARAM_UI8_CHAR, (x)
309
310 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_SHORT
311  *
312  * NAME
313  *
314  *    #define SILC_STR_UI_SHORT() ...
315  *    #define SILC_STR_SI_SHORT() ...
316  *
317  * DESCRIPTION
318  *
319  *    SilcInt16/SilcUInt16.
320  *
321  *    Formatting:    SILC_STR_SI_SHORT(short)
322  *                   SILC_STR_UI_SHORT(SilcUInt16)
323  *    Unformatting:  SILC_STR_SI_SHORT(short *)
324  *                   SILC_STR_UI_SHORT(SilcUInt16 *)
325  *
326  ***/
327 #define SILC_STR_SI_SHORT(x) SILC_PARAM_SI16_SHORT, (x)
328 #define SILC_STR_UI_SHORT(x) SILC_PARAM_UI16_SHORT, (x)
329
330 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT
331  *
332  * NAME
333  *
334  *    #define SILC_STR_UI_INT() ...
335  *    #define SILC_STR_SI_INT() ...
336  *
337  * DESCRIPTION
338  *
339  *    SilcInt32/SilcUInt32.
340  *
341  *    Formatting:    SILC_STR_SI_INT(int)
342  *                   SILC_STR_UI_INT(SilcUInt32)
343  *    Unformatting:  SILC_STR_SI_INT(int *)
344  *                   SILC_STR_UI_INT(SilcUInt32 *)
345  *
346  ***/
347 #define SILC_STR_SI_INT(x) SILC_PARAM_SI32_INT, (x)
348 #define SILC_STR_UI_INT(x) SILC_PARAM_UI32_INT, (x)
349
350 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT64
351  *
352  * NAME
353  *
354  *    #define SILC_STR_UI_INT64() ...
355  *    #define SILC_STR_SI_INT64() ...
356  *
357  * DESCRIPTION
358  *
359  *    SilcInt64/SilcUInt64.
360  *
361  *     Formatting:    SILC_STR_SI_INT64(int)
362  *                    SILC_STR_UI_INT64(SilcUInt32)
363  *     Unformatting:  SILC_STR_SI_INT64(int *)
364  *                    SILC_STR_UI_INT64(SilcUInt32 *)
365  *
366  ***/
367 #define SILC_STR_SI_INT64(x) SILC_PARAM_SI64_INT, (x)
368 #define SILC_STR_UI_INT64(x) SILC_PARAM_UI64_INT, (x)
369
370 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_STRING
371  *
372  * NAME
373  *
374  *    #define SILC_STR_UI8_STRING() ...
375  *    #define SILC_STR_UI8_STRING_ALLOC() ...
376  *    #define SILC_STR_UI16_STRING() ...
377  *    #define SILC_STR_UI16_STRING_ALLOC() ...
378  *    #define SILC_STR_UI32_STRING() ...
379  *    #define SILC_STR_UI32_STRING_ALLOC() ...
380  *
381  * DESCRIPTION
382  *
383  *    Unsigned NULL terminated string. Note that the string must be
384  *    NULL terminated because strlen() will be used to get the length of
385  *    the string.
386  *
387  *    Formatting:    SILC_STR_UI32_STRING(unsigned char *)
388  *    Unformatting:  SILC_STR_UI32_STRING(unsigned char **)
389  *
390  *    Unformatting procedure will check for length of the string from the
391  *    buffer before trying to get the string out. Thus, one *must* format the
392  *    length as UI_INT or UI_SHORT into the buffer *before* formatting the
393  *    actual string to the buffer, and, in unformatting one must ignore the
394  *    length of the string because unformatting procedure will take it
395  *    automatically.
396  *
397  *    Example:
398  *
399  *    Formatting:    ..., SILC_STR_UI_INT(strlen(string)),
400  *                        SILC_STR_UI32_STRING(string), ...
401  *    Unformatting:  ..., SILC_STR_UI32_STRING(&string), ...
402  *
403  *    I.e., you can ignore the formatted length field in unformatting.
404  *
405  *    UI8, UI16 and UI32 means that the length is considered to be
406  *    either char (8 bits), short (16 bits) or int (32 bits) in
407  *    unformatting.
408  *
409  *    _ALLOC routines automatically allocates memory for the variable sent
410  *    as argument in unformatting.
411  *
412  ***/
413 #define SILC_STR_UI8_STRING(x) SILC_PARAM_UI8_STRING, (x)
414 #define SILC_STR_UI8_STRING_ALLOC(x) SILC_PARAM_UI8_STRING_ALLOC, (x)
415 #define SILC_STR_UI16_STRING(x) SILC_PARAM_UI16_STRING, (x)
416 #define SILC_STR_UI16_STRING_ALLOC(x) SILC_PARAM_UI16_STRING_ALLOC, (x)
417 #define SILC_STR_UI32_STRING(x) SILC_PARAM_UI32_STRING, (x)
418 #define SILC_STR_UI32_STRING_ALLOC(x) SILC_PARAM_UI32_STRING_ALLOC, (x)
419
420 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_NSTRING
421  *
422  * NAME
423  *
424  *    #define SILC_STR_UI8_NSTRING() ...
425  *    #define SILC_STR_UI8_NSTRING_ALLOC() ...
426  *    #define SILC_STR_UI16_NSTRING() ...
427  *    #define SILC_STR_UI16_NSTRING_ALLOC() ...
428  *    #define SILC_STR_UI32_NSTRING() ...
429  *    #define SILC_STR_UI32_NSTRING_ALLOC() ...
430  *
431  * DESCRIPTION
432  *
433  *    Unsigned string. Second argument is the length of the string.
434  *
435  *    Formatting:    SILC_STR_UI32_NSTRING(unsigned char *, SilcUInt32)
436  *    Unformatting:  SILC_STR_UI32_NSTRING(unsigned char **, SilcUInt32 *)
437  *
438  *    Unformatting procedure will check for length of the string from the
439  *    buffer before trying to get the string out. Thus, one *must* format the
440  *    length as UI_INT or UI_SHORT into the buffer *before* formatting the
441  *    actual string to the buffer, and, in unformatting one must ignore the
442  *    length of the string because unformatting procedure will take it
443  *    automatically.
444  *
445  *     Example:
446  *
447  *     Formatting:    ..., SILC_STR_UI_INT(strlen(string)),
448  *                         SILC_STR_UI32_NSTRING(string, strlen(string)), ...
449  *     Unformatting:  ..., SILC_STR_UI32_NSTRING(&string, &len), ...
450  *
451  *    I.e., you can ignore the formatted length field in unformatting. The
452  *    length taken from the buffer is returned to the pointer sent as
453  *    argument (&len in above example).
454  *
455  *    UI8, UI16 and UI32 means that the length is considered to be
456  *    either char (8 bits), short (16 bits) or int (32 bits) in
457  *    unformatting.
458  *
459  *    _ALLOC routines automatically allocates memory for the variable sent
460  *    as argument in unformatting.
461  *
462  ***/
463 #define SILC_STR_UI8_NSTRING(x, l) SILC_PARAM_UI8_NSTRING, (x), (l)
464 #define SILC_STR_UI8_NSTRING_ALLOC(x, l) \
465   SILC_PARAM_UI8_NSTRING_ALLOC, (x), (l)
466 #define SILC_STR_UI16_NSTRING(x, l) SILC_PARAM_UI16_NSTRING, (x), (l)
467 #define SILC_STR_UI16_NSTRING_ALLOC(x, l) \
468   SILC_PARAM_UI16_NSTRING_ALLOC, (x), (l)
469 #define SILC_STR_UI32_NSTRING(x, l) SILC_PARAM_UI32_NSTRING, (x), (l)
470 #define SILC_STR_UI32_NSTRING_ALLOC(x, l) \
471   SILC_PARAM_UI32_NSTRING_ALLOC, (x), (l)
472
473 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA
474  *
475  * NAME
476  *
477  *    #define SILC_STR_DATA() ...
478  *    #define SILC_STR_DATA_ALLOC() ...
479  *
480  * DESCRIPTION
481  *
482  *    Binary data formatting.  Second argument is the length of the data.
483  *
484  *    Formatting:    SILC_STR_DATA(unsigned char *, SilcUInt32)
485  *    Unformatting:  SILC_STR_DATA(unsigned char **, SilcUInt32)
486  *
487  *    This type can be used to take arbitrary size data block from the buffer
488  *    by sending the requested amount of bytes as argument.
489  *
490  *    _ALLOC routines automatically allocates memory for the variable sent
491  *    as argument in unformatting.
492  *
493  ***/
494 #define SILC_STR_DATA(x, l) SILC_PARAM_DATA, (x), (l)
495 #define SILC_STR_DATA_ALLOC(x, l) SILC_PARAM_DATA_ALLOC, (x), (l)
496
497 /* Deprecated */
498 #define SILC_STR_UI_XNSTRING(x, l) SILC_PARAM_UI_XNSTRING, (x), (l)
499 #define SILC_STR_UI_XNSTRING_ALLOC(x, l) SILC_PARAM_UI_XNSTRING_ALLOC, (x), (l)
500
501 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_BUFFER
502  *
503  * NAME
504  *
505  *    #define SILC_STR_BUFFER() ...
506  *    #define SILC_STR_BUFFER_ALLOC() ...
507  *
508  * DESCRIPTION
509  *
510  *    SilcBuffer formatting.
511  *
512  *    Formatting:    SILC_STR_DATA(SilcBuffer)
513  *    Unformatting:  SILC_STR_DATA(SilcBuffer)
514  *
515  *    This type can be used to format and unformat SilcBuffer.  The lenght
516  *    of the buffer will be automatically encoded into the buffer as a 32-bit
517  *    integer.  In unformatting the SilcBuffer context must be pre-allocated.
518  *
519  *    _ALLOC routines automatically allocates memory inside SilcBuffer in
520  *    unformatting.
521  *
522  ***/
523 #define SILC_STR_BUFFER(x) SILC_BUFFER_DATA, (x)
524 #define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER_ALLOC, (x)
525
526 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET
527  *
528  * NAME
529  *
530  *    #define SILC_STR_OFFSET() ...
531  *
532  * DESCRIPTION
533  *
534  *    Offset in buffer.  This can be used in formatting and unformatting to
535  *    move the data pointer of the buffer either forwards (positive offset)
536  *    or backwards (negative offset).  It can be used to for example skip
537  *    some types during unformatting.
538  *
539  *    Example:
540  *
541  *    ..., SILC_STR_OFFSET(5), ...
542  *    ..., SILC_STR_OFFSET(-3), ...
543  *
544  *    Moves the data pointer at the point of the offset either forward
545  *    or backward and then moves to the next type.  Multiple SILC_STR_OFFSETs
546  *    can be used in formatting and unformatting at the same time.
547  *
548  ***/
549 #define SILC_STR_OFFSET(x) SILC_PARAM_OFFSET, (x)
550
551 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE
552  *
553  * NAME
554  *
555  *    #define SILC_STR_ADVANCE ...
556  *
557  * DESCRIPTION
558  *
559  *    Advance the buffer to the end of the data after the formatting is
560  *    done.  In normal operation when the formatted data is written the
561  *    buffer is located at the start of the data.  With SILC_STR_ADVANCE
562  *    the buffer will be located at the end of the data.  This makes it
563  *    easy to add new data immediately after the previously added data.
564  *
565  * EXAMPLE
566  *
567  *    do {
568  *      len = read(fd, buf, sizeof(buf));
569  *      if (len > 0)
570  *        // Add read data to the buffer
571  *        silc_buffer_format(buffer,
572  *                           SILC_STR_ADVANCE,
573  *                           SILC_STR_UI_XNSTRING(buf, len),
574  *                           SILC_STR_END);
575  *    } while (len > 0);
576  *
577  *    // Move to beginning of buffer
578  *    silc_buffer_push(buffer, silc_buffer_truelen(buffer));
579  *
580  ***/
581 #define SILC_STR_ADVANCE SILC_PARAM_ADVANCE
582
583 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_END
584  *
585  * NAME
586  *
587  *    #define SILC_STR_END ...
588  *
589  * DESCRIPTION
590  *
591  *    Marks end of the argument list. This must be at the end of the
592  *    argument list or error will occur.
593  *
594  ***/
595 #define SILC_STR_END SILC_PARAM_END
596
597 /****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END
598  *
599  * NAME
600  *
601  *    #define SILC_STRFMT_END ...
602  *
603  * DESCRIPTION
604  *
605  *    Marks end of the argument list in silc_buffer_strformat function.
606  *    This must be at the end of the argument list or error will occur.
607  *
608  ***/
609 #define SILC_STRFMT_END (void *)SILC_STR_END
610
611 #endif  /* !SILCBUFFMT_H */