5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /****h* silcutil/SILC Buffer Format Interface
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.
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.
38 /****f* silcutil/SilcBufferFormatAPI/SilcBufferFormatFunc
42 * typedef int (*SilcBuffeSFormatFunc)(SilcStack stack,
49 * Formatting function callback given with SILC_STR_FUNC type. The
50 * `buffer' is the buffer being formatted at the location where the
51 * SILC_STR_FUNC was placed in formatting. The function should call
52 * silc_buffer_senlarge before it adds the data to the buffer to make
53 * sure that it has enough space. The buffer->head points to the
54 * start of the buffer and silc_buffer_headlen() gives the length
55 * of the currently formatted data area. It is also possible to use
56 * silc_buffer_sformat with `buffer' which will enlarge the buffer if
59 * The `value' is the value given to SILC_STR_FUNC that is to be formatted
60 * into the buffer. It may be NULL if the function is not formatting
61 * new data into the buffer. The `context' is caller specific context.
62 * Returns -1 on error and length of the formatted value otherwise, and
63 * 0 if nothing was formatted.
66 typedef int (*SilcBufferFormatFunc)(SilcStack stack, SilcBuffer buffer,
67 void *value, void *context);
69 /****f* silcutil/SilcBufferFormatAPI/SilcBufferUnformatFunc
73 * typedef int (*SilcBufferUnformatFunc)(SilcBuffer buffer,
79 * Unformatting function callback given with SILC_STR_FUNC type. The
80 * `buffer' is the buffer being unformatted and is at the location where
81 * the SILC_STR_FUNC was placed in unformatting. The function should
82 * check there is enough data in the `buffer' before trying to decode
85 * If this function unformats anything from the buffer its value is to
86 * be returned to the `value' pointer. The implementation should itself
87 * decide whether the unformatted value is allocated or not. If this
88 * function does not unformat anything, nothing is returned to `value'
90 * The `context' is caller specific context. Returns -1 on error, and
91 * length of the unformatted value otherwise, and 0 if nothing was
95 typedef int (*SilcBufferUnformatFunc)(SilcStack stack, SilcBuffer buffer,
96 void **value, void *context);
100 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format
104 * int silc_buffer_format(SilcBuffer dst, ...);
108 * Formats a buffer from a variable argument list. Returns -1 on error
109 * and the length of the formatted buffer otherwise. The buffer is
110 * enlarged automatically during formatting, if it doesn't already have
115 * Three basic ways of using silc_buffer_format:
117 * // Statically allocated zero size buffer
118 * SilcBufferStruct buffer;
120 * memset(&buffer, 0, sizeof(buffer));
121 * ret = silc_buffer_format(&buffer,
122 * SILC_STR_UI_INT(intval),
123 * SILC_STR_CHAR(charval),
124 * SILC_STR_UI_INT(intval),
125 * SILC_STR_SHORT(str_len),
126 * SILC_STR_DATA(str, str_len),
131 * // Free the allocated data
132 * silc_buffer_purge(&buffer);
134 * // Dynamically allocated zero size buffer
136 * buf = silc_buffer_alloc(0);
137 * ret = silc_buffer_format(buf,
138 * SILC_STR_UI_INT(intval),
139 * SILC_STR_CHAR(charval),
144 * // Free the allocated buffer
145 * silc_buffer_free(buf);
147 * // Dynamically allocated buffer with enough space
149 * buf = silc_buffer_alloc(2 + str_len);
150 * ret = silc_buffer_format(buf,
151 * SILC_STR_UI_SHORT(str_len),
152 * SILC_STR_DATA(str, str_len),
158 int silc_buffer_format(SilcBuffer dst, ...);
160 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat
164 * int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
168 * Same as silc_buffer_format but uses `stack' to allocate the memory.
169 * if `stack' is NULL reverts back to silc_buffer_format call.
171 * Note that this call consumes the `stack'. The caller should push the
172 * stack before calling the function and pop it later.
175 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
177 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
181 * int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
185 * Formats a buffer from a variable argument list indicated by the `ap'.
186 * Returns -1 on error and the length of the formatted buffer otherwise.
189 int silc_buffer_format_vp(SilcBuffer dst, va_list ap);
191 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat_vp
195 * int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list vp);
199 * Same as silc_buffer_format_vp but uses `stack' to allocate the memory.
200 * if `stack' is NULL reverts back to silc_buffer_format_vp call.
202 * Note that this call consumes the `stack'. The caller should push the
203 * stack before calling the function and pop it later.
206 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap);
208 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat
212 * int silc_buffer_unformat(SilcBuffer src, ...);
216 * Unformats a buffer from a variable argument list. Returns -1 on error
217 * and the length of the unformatted buffer otherwise.
221 * ret = silc_buffer_unformat(buffer,
222 * SILC_STR_UI_INT(&intval),
223 * SILC_STR_CHAR(&charval),
224 * SILC_STR_OFFSET(4),
225 * SILC_STR_UI16_NSTRING_ALLOC(&str, &str_len),
231 int silc_buffer_unformat(SilcBuffer src, ...);
233 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat
237 * int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...);
241 * Same as silc_buffer_unformat but uses `stack' to allocate the memory.
242 * if `stack' is NULL reverts back to silc_buffer_format call.
244 * Note that this call consumes the `stack'. The caller should push the
245 * stack before calling the function and pop it later.
248 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...);
250 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat_vp
254 * int silc_buffer_unformat_vp(SilcBuffer src, va_list vp);
258 * Unformats a buffer from a variable argument list indicated by the `ap'.
259 * Returns -1 on error and the length of the unformatted buffer otherwise.
262 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap);
264 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat_vp
268 * int silc_buffer_sunformat_vp(SilcBuffer src, va_list vp);
272 * Same as silc_buffer_unformat_vp but uses `stack' to allocate the
273 * memory. if `stack' is NULL reverts back to silc_buffer_format_vp call.
275 * Note that this call consumes the `stack'. The caller should push the
276 * stack before calling the function and pop it later.
279 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap);
281 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_strformat
285 * int silc_buffer_strformat(SilcBuffer dst, ...);
289 * Formats a buffer from variable argument list of strings. Each
290 * string must be NULL-terminated and the variable argument list must
291 * be end with SILC_STRFMT_END argument. This allows that a string in
292 * the list can be NULL, in which case it is skipped. This automatically
293 * allocates the space for the buffer data but `dst' must be already
294 * allocated by the caller.
298 * ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STRFMT_END);
303 int silc_buffer_strformat(SilcBuffer dst, ...);
305 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sstrformat
309 * int silc_buffer_strformat(SilcStack stack, SilcBuffer dst, ...);
313 * Formats a buffer from variable argument list of strings. Each
314 * string must be NULL-terminated and the variable argument list must
315 * be end with SILC_STRFMT_END argument. This allows that a string in
316 * the list can be NULL, in which case it is skipped. This automatically
317 * allocates the space for the buffer data but `dst' must be already
318 * allocated by the caller. This function is equivalent to
319 * silc_buffer_strformat but allocates memory from `stack'.
321 * Note that this call consumes the `stack'. The caller should push the
322 * stack before calling the function and pop it later.
325 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...);
327 /****d* silcutil/SilcBufferFormatAPI/SilcBufferParamType
331 * typedef enum { ... } SilcBufferParamType;
335 * Buffer parameter types. These are not needed when formatting or
336 * unformatting buffers. Use the macros such as SILC_STR_UI_CHAR and
337 * others instead. These types may be used when describing what a
338 * buffer looks like, and how it may be formatted and unformatted.
343 SILC_PARAM_SI8_CHAR, /* Signed 8-bit char */
344 SILC_PARAM_UI8_CHAR, /* Unsigned 8-bit char */
345 SILC_PARAM_SI16_SHORT, /* Signed 16-bit int */
346 SILC_PARAM_UI16_SHORT, /* Unsigned 16-bit int */
347 SILC_PARAM_SI32_INT, /* Signed 32-bit int */
348 SILC_PARAM_UI32_INT, /* Unsigned 32-bit int */
349 SILC_PARAM_SI64_INT, /* Signed 64-bit int */
350 SILC_PARAM_UI64_INT, /* Unsigned 64-bit int */
351 SILC_PARAM_UI8_STRING, /* String (max len 8-bits)*/
352 SILC_PARAM_UI16_STRING, /* String (max len 16-bits) */
353 SILC_PARAM_UI32_STRING, /* String (max len 32-bits) */
354 SILC_PARAM_BUFFER, /* SilcBuffer */
357 SILC_PARAM_DATA, /* Binary data */
358 SILC_PARAM_UI8_NSTRING, /* String (max len 8-bits) */
359 SILC_PARAM_UI16_NSTRING, /* String (max len 16-bits) */
360 SILC_PARAM_UI32_NSTRING, /* String (max len 32-bits) */
361 SILC_PARAM_UI8_STRING_ALLOC, /* Alloc + memcpy */
362 SILC_PARAM_UI16_STRING_ALLOC, /* Alloc + memcpy */
363 SILC_PARAM_UI32_STRING_ALLOC, /* Alloc + memcpy */
364 SILC_PARAM_UI8_NSTRING_ALLOC, /* Alloc + memcpy */
365 SILC_PARAM_UI16_NSTRING_ALLOC, /* Alloc + memcpy */
366 SILC_PARAM_UI32_NSTRING_ALLOC, /* Alloc + memcpy */
367 SILC_PARAM_DATA_ALLOC, /* Alloc + memcpy */
368 SILC_PARAM_BUFFER_ALLOC, /* Alloc + memcpy */
374 SILC_PARAM_UI_XNSTRING,
375 SILC_PARAM_UI_XNSTRING_ALLOC,
378 } SilcBufferParamType;
381 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_CHAR
385 * #define SILC_STR_UI_CHAR() ...
386 * #define SILC_STR_SI_CHAR() ...
390 * One signed/unsigned character.
392 * Formatting: SILC_STR_SI_CHAR(char)
393 * SILC_STR_UI_CHAR(unsigned char)
394 * Unformatting: SILC_STR_SI_CHAR(char *)
395 * SILC_STR_UI_CHAR(unsigned char *)
398 #define SILC_STR_SI_CHAR(x) SILC_PARAM_SI8_CHAR, (x)
399 #define SILC_STR_UI_CHAR(x) SILC_PARAM_UI8_CHAR, (x)
401 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_SHORT
405 * #define SILC_STR_UI_SHORT() ...
406 * #define SILC_STR_SI_SHORT() ...
410 * SilcInt16/SilcUInt16.
412 * Formatting: SILC_STR_SI_SHORT(SilcInt16)
413 * SILC_STR_UI_SHORT(SilcUInt16)
414 * Unformatting: SILC_STR_SI_SHORT(SilcInt16 *)
415 * SILC_STR_UI_SHORT(SilcUInt16 *)
418 #define SILC_STR_SI_SHORT(x) SILC_PARAM_SI16_SHORT, (x)
419 #define SILC_STR_UI_SHORT(x) SILC_PARAM_UI16_SHORT, (x)
421 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT
425 * #define SILC_STR_UI_INT() ...
426 * #define SILC_STR_SI_INT() ...
430 * SilcInt32/SilcUInt32.
432 * Formatting: SILC_STR_SI_INT(SilcInt32)
433 * SILC_STR_UI_INT(SilcUInt32)
434 * Unformatting: SILC_STR_SI_INT(SilcInt32 *)
435 * SILC_STR_UI_INT(SilcUInt32 *)
438 #define SILC_STR_SI_INT(x) SILC_PARAM_SI32_INT, (x)
439 #define SILC_STR_UI_INT(x) SILC_PARAM_UI32_INT, (x)
441 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT64
445 * #define SILC_STR_UI_INT64() ...
446 * #define SILC_STR_SI_INT64() ...
450 * SilcInt64/SilcUInt64.
452 * Formatting: SILC_STR_SI_INT64(SilcInt64)
453 * SILC_STR_UI_INT64(SilcUInt64)
454 * Unformatting: SILC_STR_SI_INT64(SilcInt64 *)
455 * SILC_STR_UI_INT64(SilcUInt64 *)
458 #define SILC_STR_SI_INT64(x) SILC_PARAM_SI64_INT, (x)
459 #define SILC_STR_UI_INT64(x) SILC_PARAM_UI64_INT, (x)
461 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_STRING
465 * #define SILC_STR_UI8_STRING() ...
466 * #define SILC_STR_UI8_STRING_ALLOC() ...
467 * #define SILC_STR_UI16_STRING() ...
468 * #define SILC_STR_UI16_STRING_ALLOC() ...
469 * #define SILC_STR_UI32_STRING() ...
470 * #define SILC_STR_UI32_STRING_ALLOC() ...
474 * Unsigned NULL terminated string. Note that the string must be
475 * NULL terminated because strlen() will be used to get the length of
478 * Formatting: SILC_STR_UI32_STRING(unsigned char *)
479 * Unformatting: SILC_STR_UI32_STRING(unsigned char **)
481 * Unformatting procedure will check for length of the string from the
482 * buffer before trying to get the string out. Thus, one *must* format the
483 * length as UI_INT or UI_SHORT into the buffer *before* formatting the
484 * actual string to the buffer, and, in unformatting one must ignore the
485 * length of the string because unformatting procedure will take it
490 * Formatting: ..., SILC_STR_UI_INT(strlen(string)),
491 * SILC_STR_UI32_STRING(string), ...
492 * Unformatting: ..., SILC_STR_UI32_STRING(&string), ...
494 * I.e., you can ignore the formatted length field in unformatting.
496 * UI8, UI16 and UI32 means that the length is considered to be
497 * either char (8 bits), short (16 bits) or int (32 bits) in
500 * _ALLOC routines automatically allocates memory for the variable sent
501 * as argument in unformatting.
504 #define SILC_STR_UI8_STRING(x) SILC_PARAM_UI8_STRING, (x)
505 #define SILC_STR_UI8_STRING_ALLOC(x) SILC_PARAM_UI8_STRING_ALLOC, (x)
506 #define SILC_STR_UI16_STRING(x) SILC_PARAM_UI16_STRING, (x)
507 #define SILC_STR_UI16_STRING_ALLOC(x) SILC_PARAM_UI16_STRING_ALLOC, (x)
508 #define SILC_STR_UI32_STRING(x) SILC_PARAM_UI32_STRING, (x)
509 #define SILC_STR_UI32_STRING_ALLOC(x) SILC_PARAM_UI32_STRING_ALLOC, (x)
511 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_NSTRING
515 * #define SILC_STR_UI8_NSTRING() ...
516 * #define SILC_STR_UI8_NSTRING_ALLOC() ...
517 * #define SILC_STR_UI16_NSTRING() ...
518 * #define SILC_STR_UI16_NSTRING_ALLOC() ...
519 * #define SILC_STR_UI32_NSTRING() ...
520 * #define SILC_STR_UI32_NSTRING_ALLOC() ...
524 * Unsigned string. Second argument is the length of the string.
526 * Formatting: SILC_STR_UI32_NSTRING(unsigned char *, SilcUInt32)
527 * Unformatting: SILC_STR_UI32_NSTRING(unsigned char **, SilcUInt32 *)
529 * Unformatting procedure will check for length of the string from the
530 * buffer before trying to get the string out. Thus, one *must* format the
531 * length as UI_INT or UI_SHORT into the buffer *before* formatting the
532 * actual string to the buffer, and, in unformatting one must ignore the
533 * length of the string because unformatting procedure will take it
538 * Formatting: ..., SILC_STR_UI_INT(strlen(string)),
539 * SILC_STR_UI32_NSTRING(string, strlen(string)), ...
540 * Unformatting: ..., SILC_STR_UI32_NSTRING(&string, &len), ...
542 * I.e., you can ignore the formatted length field in unformatting. The
543 * length taken from the buffer is returned to the pointer sent as
544 * argument (&len in above example).
546 * UI8, UI16 and UI32 means that the length is considered to be
547 * either char (8 bits), short (16 bits) or int (32 bits) in
550 * _ALLOC routines automatically allocates memory for the variable sent
551 * as argument in unformatting.
554 #define SILC_STR_UI8_NSTRING(x, l) SILC_PARAM_UI8_NSTRING, (x), (l)
555 #define SILC_STR_UI8_NSTRING_ALLOC(x, l) \
556 SILC_PARAM_UI8_NSTRING_ALLOC, (x), (l)
557 #define SILC_STR_UI16_NSTRING(x, l) SILC_PARAM_UI16_NSTRING, (x), (l)
558 #define SILC_STR_UI16_NSTRING_ALLOC(x, l) \
559 SILC_PARAM_UI16_NSTRING_ALLOC, (x), (l)
560 #define SILC_STR_UI32_NSTRING(x, l) SILC_PARAM_UI32_NSTRING, (x), (l)
561 #define SILC_STR_UI32_NSTRING_ALLOC(x, l) \
562 SILC_PARAM_UI32_NSTRING_ALLOC, (x), (l)
564 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA
568 * #define SILC_STR_DATA() ...
569 * #define SILC_STR_DATA_ALLOC() ...
573 * Binary data formatting. Second argument is the length of the data.
575 * Formatting: SILC_STR_DATA(unsigned char *, SilcUInt32)
576 * Unformatting: SILC_STR_DATA(unsigned char **, SilcUInt32)
578 * This type can be used to take arbitrary size data block from the buffer
579 * by sending the requested amount of bytes as argument.
581 * _ALLOC routines automatically allocates memory for the variable sent
582 * as argument in unformatting.
585 #define SILC_STR_DATA(x, l) SILC_PARAM_DATA, (x), (l)
586 #define SILC_STR_DATA_ALLOC(x, l) SILC_PARAM_DATA_ALLOC, (x), (l)
589 #define SILC_STR_UI_XNSTRING(x, l) SILC_PARAM_UI_XNSTRING, (x), (l)
590 #define SILC_STR_UI_XNSTRING_ALLOC(x, l) SILC_PARAM_UI_XNSTRING_ALLOC, (x), (l)
592 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_BUFFER
596 * #define SILC_STR_BUFFER() ...
597 * #define SILC_STR_BUFFER_ALLOC() ...
601 * SilcBuffer formatting.
603 * Formatting: SILC_STR_BUFFER(SilcBuffer)
604 * Unformatting: SILC_STR_BUFFER(SilcBuffer)
606 * This type can be used to format and unformat SilcBuffer. Note that, the
607 * length of the buffer will be automatically encoded into the buffer as
608 * a 32-bit integer. In unformatting the SilcBuffer context must be
611 * _ALLOC routines automatically allocates memory inside SilcBuffer in
615 #define SILC_STR_BUFFER(x) SILC_PARAM_BUFFER, (x)
616 #define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER_ALLOC, (x)
618 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_FUNC
622 * #define SILC_STR_FUNC() ...
626 * SilcBuffer formatting.
628 * Formatting: SILC_STR_FUNC(function, void *value, void *context)
629 * Unformatting: SILC_STR_FUNC(function, void **value, void *context)
631 * This type can be used to call the `function' of the type
632 * SilcBufferFormatFunc or SilcBufferUnformatFunc to encode or decode
633 * the `value'. In encoding the `value' will be passed to the `function'
634 * and can be encoded into the buffer. The buffer will be passed as
635 * well to the `function' at the location where SILC_STR_FUNC is placed
636 * in formatting. The `context' delivers caller specific context to
639 * In unformatting the `function' will decode the encoded type and
640 * return it to `value' pointer. The decoding function should decide
641 * itself whether to allocate or not the decoded value.
643 * The `function' does not have to encode anything and passing `value'
644 * as NULL is allowed. The `function' could for example modify the
649 * // Encode payload, encrypt and compute MAC.
650 * silc_buffer_format(buf,
651 * SILC_STR_FUNC(foo_encode_id, id, ctx),
652 * SILC_STR_UI_SHORT(len),
653 * SILC_STR_DATA(data, len),
654 * SILC_STR_FUNC(foo_buf_encrypt, NULL, key),
655 * SILC_STR_FUNC(foo_buf_hmac, NULL, hmac),
656 * SILC_STR_DATA(iv, iv_len);
659 * // Check MAC, decrypt and decode payload
660 * silc_buffer_unformat(buf,
661 * SILC_STR_FUNC(foo_buf_hmac, NULL, hmac),
662 * SILC_STR_FUNC(foo_buf_decrypt, NULL, key),
663 * SILC_STR_FUNC(foo_decode_id, &id, ctx),
664 * SILC_STR_UI_SHORT(&len),
668 #define SILC_STR_FUNC(func, val, context) SILC_PARAM_FUNC, \
669 func, (val), (context)
671 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET
675 * #define SILC_STR_OFFSET() ...
679 * Offset in buffer. This can be used in formatting and unformatting to
680 * move the data pointer of the buffer either forwards (positive offset)
681 * or backwards (negative offset). It can be used to for example skip
682 * some types during unformatting.
686 * ..., SILC_STR_OFFSET(5), ...
687 * ..., SILC_STR_OFFSET(-3), ...
689 * Moves the data pointer at the point of the offset either forward
690 * or backward and then moves to the next type. Multiple SILC_STR_OFFSETs
691 * can be used in formatting and unformatting at the same time.
694 #define SILC_STR_OFFSET(x) SILC_PARAM_OFFSET, (x)
696 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE
700 * #define SILC_STR_ADVANCE ...
704 * Advance the buffer to the end of the data after the formatting is
705 * done. In normal operation when the formatted data is written the
706 * buffer is located at the start of the data. With SILC_STR_ADVANCE
707 * the buffer will be located at the end of the data. This makes it
708 * easy to add new data immediately after the previously added data.
709 * The SILC_STR_ADVANCE may also be used in unformatting.
714 * len = read(fd, buf, sizeof(buf));
716 * // Add read data to the buffer
717 * silc_buffer_format(buffer,
719 * SILC_STR_DATA(buf, len),
723 * // Move to beginning of buffer
724 * silc_buffer_start(buffer);
727 #define SILC_STR_ADVANCE SILC_PARAM_ADVANCE
729 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_END
733 * #define SILC_STR_END ...
737 * Marks end of the argument list. This must be at the end of the
738 * argument list or error will occur.
741 #define SILC_STR_END SILC_PARAM_END
743 /****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END
747 * #define SILC_STRFMT_END ...
751 * Marks end of the argument list in silc_buffer_strformat function.
752 * This must be at the end of the argument list or error will occur.
755 #define SILC_STRFMT_END (void *)SILC_STR_END
757 #endif /* !SILCBUFFMT_H */