5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 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.
40 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format
44 * int silc_buffer_format(SilcBuffer dst, ...);
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
55 * SilcBufferStruct buffer;
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),
69 * // Free the allocated data
70 * silc_buffer_purge(&buffer);
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),
79 * // Free the allocated buffer
80 * silc_buffer_free(buf);
83 int silc_buffer_format(SilcBuffer dst, ...);
85 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat
89 * int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
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.
97 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
99 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
103 * int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
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.
111 int silc_buffer_format_vp(SilcBuffer dst, va_list ap);
113 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
117 * int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
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.
125 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap);
127 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat
131 * int silc_buffer_unformat(SilcBuffer src, ...);
135 * Unformats a buffer from a variable argument list. Returns -1 on error
136 * and the length of the unformatted buffer otherwise.
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),
150 int silc_buffer_unformat(SilcBuffer src, ...);
152 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat
156 * int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...);
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.
164 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...);
166 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat_vp
170 * int silc_buffer_unformat_vp(SilcBuffer src, va_list vp);
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.
178 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap);
180 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sunformat_vp
184 * int silc_buffer_sunformat_vp(SilcBuffer src, va_list vp);
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.
192 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap);
194 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_strformat
198 * int silc_buffer_strformat(SilcBuffer dst, ...);
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.
211 * ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STRFMT_END);
216 int silc_buffer_strformat(SilcBuffer dst, ...);
218 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sstrformat
222 * int silc_buffer_strformat(SilcStack stack, SilcBuffer dst, ...);
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'.
235 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...);
237 /****d* silcutil/SilcBufferFormatAPI/SilcBufferParamType
241 * typedef enum { ... } SilcBufferParamType;
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.
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 */
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 */
283 SILC_PARAM_UI_XNSTRING,
284 SILC_PARAM_UI_XNSTRING_ALLOC,
287 } SilcBufferParamType;
290 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_CHAR
294 * #define SILC_STR_UI_CHAR() ...
295 * #define SILC_STR_SI_CHAR() ...
299 * One signed/unsigned character.
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 *)
307 #define SILC_STR_SI_CHAR(x) SILC_PARAM_SI8_CHAR, (x)
308 #define SILC_STR_UI_CHAR(x) SILC_PARAM_UI8_CHAR, (x)
310 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_SHORT
314 * #define SILC_STR_UI_SHORT() ...
315 * #define SILC_STR_SI_SHORT() ...
319 * SilcInt16/SilcUInt16.
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 *)
327 #define SILC_STR_SI_SHORT(x) SILC_PARAM_SI16_SHORT, (x)
328 #define SILC_STR_UI_SHORT(x) SILC_PARAM_UI16_SHORT, (x)
330 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT
334 * #define SILC_STR_UI_INT() ...
335 * #define SILC_STR_SI_INT() ...
339 * SilcInt32/SilcUInt32.
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 *)
347 #define SILC_STR_SI_INT(x) SILC_PARAM_SI32_INT, (x)
348 #define SILC_STR_UI_INT(x) SILC_PARAM_UI32_INT, (x)
350 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT64
354 * #define SILC_STR_UI_INT64() ...
355 * #define SILC_STR_SI_INT64() ...
359 * SilcInt64/SilcUInt64.
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 *)
367 #define SILC_STR_SI_INT64(x) SILC_PARAM_SI64_INT, (x)
368 #define SILC_STR_UI_INT64(x) SILC_PARAM_UI64_INT, (x)
370 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_STRING
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() ...
383 * Unsigned NULL terminated string. Note that the string must be
384 * NULL terminated because strlen() will be used to get the length of
387 * Formatting: SILC_STR_UI32_STRING(unsigned char *)
388 * Unformatting: SILC_STR_UI32_STRING(unsigned char **)
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
399 * Formatting: ..., SILC_STR_UI_INT(strlen(string)),
400 * SILC_STR_UI32_STRING(string), ...
401 * Unformatting: ..., SILC_STR_UI32_STRING(&string), ...
403 * I.e., you can ignore the formatted length field in unformatting.
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
409 * _ALLOC routines automatically allocates memory for the variable sent
410 * as argument in unformatting.
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)
420 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_NSTRING
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() ...
433 * Unsigned string. Second argument is the length of the string.
435 * Formatting: SILC_STR_UI32_NSTRING(unsigned char *, SilcUInt32)
436 * Unformatting: SILC_STR_UI32_NSTRING(unsigned char **, SilcUInt32 *)
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
447 * Formatting: ..., SILC_STR_UI_INT(strlen(string)),
448 * SILC_STR_UI32_NSTRING(string, strlen(string)), ...
449 * Unformatting: ..., SILC_STR_UI32_NSTRING(&string, &len), ...
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).
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
459 * _ALLOC routines automatically allocates memory for the variable sent
460 * as argument in unformatting.
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)
473 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA
477 * #define SILC_STR_DATA() ...
478 * #define SILC_STR_DATA_ALLOC() ...
482 * Binary data formatting. Second argument is the length of the data.
484 * Formatting: SILC_STR_DATA(unsigned char *, SilcUInt32)
485 * Unformatting: SILC_STR_DATA(unsigned char **, SilcUInt32)
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.
490 * _ALLOC routines automatically allocates memory for the variable sent
491 * as argument in unformatting.
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)
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)
501 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_BUFFER
505 * #define SILC_STR_BUFFER() ...
506 * #define SILC_STR_BUFFER_ALLOC() ...
510 * SilcBuffer formatting.
512 * Formatting: SILC_STR_DATA(SilcBuffer)
513 * Unformatting: SILC_STR_DATA(SilcBuffer)
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.
519 * _ALLOC routines automatically allocates memory inside SilcBuffer in
523 #define SILC_STR_BUFFER(x) SILC_BUFFER_DATA, (x)
524 #define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER_ALLOC, (x)
526 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET
530 * #define SILC_STR_OFFSET() ...
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.
541 * ..., SILC_STR_OFFSET(5), ...
542 * ..., SILC_STR_OFFSET(-3), ...
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.
549 #define SILC_STR_OFFSET(x) SILC_PARAM_OFFSET, (x)
551 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE
555 * #define SILC_STR_ADVANCE ...
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.
568 * len = read(fd, buf, sizeof(buf));
570 * // Add read data to the buffer
571 * silc_buffer_format(buffer,
573 * SILC_STR_UI_XNSTRING(buf, len),
577 * // Move to beginning of buffer
578 * silc_buffer_push(buffer, silc_buffer_truelen(buffer));
581 #define SILC_STR_ADVANCE SILC_PARAM_ADVANCE
583 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_END
587 * #define SILC_STR_END ...
591 * Marks end of the argument list. This must be at the end of the
592 * argument list or error will occur.
595 #define SILC_STR_END SILC_PARAM_END
597 /****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END
601 * #define SILC_STRFMT_END ...
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.
609 #define SILC_STRFMT_END (void *)SILC_STR_END
611 #endif /* !SILCBUFFMT_H */