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.
36 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format
40 * int silc_buffer_format(SilcBuffer dst, ...);
44 * Formats a buffer from a variable argument list. Returns -1 on error
45 * and the length of the formatted buffer otherwise. The buffer is
46 * enlarged automatically during formatting, if it doesn't already have
51 * SilcBufferStruct buffer;
54 * memset(&buffer, 0, sizeof(buffer));
55 * ret = silc_buffer_format(&buffer,
56 * SILC_STR_INT(intval),
57 * SILC_STR_CHAR(charval),
58 * SILC_STR_INT(intval),
59 * SILC_STR_SHORT(str_len),
60 * SILC_STR_UI_XNSTRING(str, str_len),
65 * // Free the allocated data
66 * silc_buffer_purge(&buffer);
68 * // Allocate zero size buffer
69 * buf = silc_buffer_alloc(0);
70 * ret = silc_buffer_format(buf,
71 * SILC_STR_INT(intval),
72 * SILC_STR_CHAR(charval),
75 * // Free the allocated buffer
76 * silc_buffer_free(buf);
79 int silc_buffer_format(SilcBuffer dst, ...);
81 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat
85 * int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
89 * Same as silc_buffer_format but uses `stack' to allocate the memory.
90 * if `stack' is NULL reverts back to silc_buffer_format call.
93 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
95 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
99 * int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
103 * Formats a buffer from a variable argument list indicated by the `ap'.
104 * Returns -1 on error and the length of the formatted buffer otherwise.
107 int silc_buffer_format_vp(SilcBuffer dst, va_list ap);
109 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
113 * int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
117 * Same as silc_buffer_format_vp but uses `stack' to allocate the memory.
118 * if `stack' is NULL reverts back to silc_buffer_format_vp call.
121 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap);
123 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat
127 * int silc_buffer_unformat(SilcBuffer src, ...);
131 * Unformats a buffer from a variable argument list. Returns -1 on error
132 * and the length of the unformatted buffer otherwise.
136 * ret = silc_buffer_unformat(buffer,
137 * SILC_STR_INT(&intval),
138 * SILC_STR_CHAR(&charval),
139 * SILC_STR_OFFSET(4),
140 * SILC_STR_UI16_NSTRING_ALLOC(&str, &str_len),
146 int silc_buffer_unformat(SilcBuffer src, ...);
148 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat_vp
152 * int silc_buffer_unformat_vp(SilcBuffer src, va_list vp);
156 * Unformats a buffer from a variable argument list indicated by the `ap'.
157 * Returns -1 on error and the length of the unformatted buffer otherwise.
160 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap);
162 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_strformat
166 * int silc_buffer_strformat(SilcBuffer dst, ...);
170 * Formats a buffer from variable argument list of strings. Each
171 * string must be NULL-terminated and the variable argument list must
172 * be end with SILC_STR_END argument. This allows that a string in
173 * the list can be NULL, in which case it is skipped. This automatically
174 * allocates the space for the buffer data but `dst' must be already
175 * allocated by the caller.
179 * ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STRFMT_END);
184 int silc_buffer_strformat(SilcBuffer dst, ...);
186 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sstrformat
190 * int silc_buffer_strformat(SilcStack stack, SilcBuffer dst, ...);
194 * Formats a buffer from variable argument list of strings. Each
195 * string must be NULL-terminated and the variable argument list must
196 * be end with SILC_STR_END argument. This allows that a string in
197 * the list can be NULL, in which case it is skipped. This automatically
198 * allocates the space for the buffer data but `dst' must be already
199 * allocated by the caller. This function is equivalent to
200 * silc_buffer_strformat but allocates memory from `stack'.
203 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...);
205 /****d* silcutil/SilcBufferFormatAPI/SilcBufferParamType
209 * typedef enum { ... } SilcBufferParamType;
213 * Buffer parameter types. These are not needed when formatting or
214 * unformatting buffers. Use the macros such as SILC_STR_UI_CHAR and
215 * others instead. These types may be used when describing what a
216 * buffer looks like, and how it may be formatted and unformatted.
221 SILC_PARAM_SI8_CHAR, /* Signed 8-bit char */
222 SILC_PARAM_UI8_CHAR, /* Unsigned 8-bit char */
223 SILC_PARAM_SI16_SHORT, /* Signed 16-bit int */
224 SILC_PARAM_UI16_SHORT, /* Unsigned 16-bit int */
225 SILC_PARAM_SI32_INT, /* Signed 32-bit int */
226 SILC_PARAM_UI32_INT, /* Unsigned 32-bit int */
227 SILC_PARAM_SI64_INT, /* Signed 64-bit int */
228 SILC_PARAM_UI64_INT, /* Unsigned 64-bit int */
229 SILC_PARAM_UI8_STRING, /* String (max len 8-bits)*/
230 SILC_PARAM_UI16_STRING, /* String (max len 16-bits) */
231 SILC_PARAM_UI32_STRING, /* String (max len 32-bits) */
232 SILC_PARAM_BUFFER, /* SilcBuffer */
235 SILC_PARAM_DATA, /* Binary data */
236 SILC_PARAM_UI8_NSTRING, /* String (max len 8-bits) */
237 SILC_PARAM_UI16_NSTRING, /* String (max len 16-bits) */
238 SILC_PARAM_UI32_NSTRING, /* String (max len 32-bits) */
239 SILC_PARAM_UI8_STRING_ALLOC, /* Alloc + memcpy */
240 SILC_PARAM_UI16_STRING_ALLOC, /* Alloc + memcpy */
241 SILC_PARAM_UI32_STRING_ALLOC, /* Alloc + memcpy */
242 SILC_PARAM_UI8_NSTRING_ALLOC, /* Alloc + memcpy */
243 SILC_PARAM_UI16_NSTRING_ALLOC, /* Alloc + memcpy */
244 SILC_PARAM_UI32_NSTRING_ALLOC, /* Alloc + memcpy */
245 SILC_PARAM_DATA_ALLOC, /* Alloc + memcpy */
246 SILC_PARAM_BUFFER_ALLOC, /* Alloc + memcpy */
251 SILC_PARAM_UI_XNSTRING,
252 SILC_PARAM_UI_XNSTRING_ALLOC,
255 } SilcBufferParamType;
258 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_CHAR
262 * #define SILC_STR_UI_CHAR() ...
263 * #define SILC_STR_SI_CHAR() ...
267 * One signed/unsigned character.
269 * Formatting: SILC_STR_SI_CHAR(char)
270 * SILC_STR_UI_CHAR(unsigned char)
271 * Unformatting: SILC_STR_SI_CHAR(char *)
272 * SILC_STR_UI_CHAR(unsigned char *)
275 #define SILC_STR_SI_CHAR(x) SILC_PARAM_SI8_CHAR, (x)
276 #define SILC_STR_UI_CHAR(x) SILC_PARAM_UI8_CHAR, (x)
278 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_SHORT
282 * #define SILC_STR_UI_SHORT() ...
283 * #define SILC_STR_SI_SHORT() ...
287 * SilcInt16/SilcUInt16.
289 * Formatting: SILC_STR_SI_SHORT(short)
290 * SILC_STR_UI_SHORT(SilcUInt16)
291 * Unformatting: SILC_STR_SI_SHORT(short *)
292 * SILC_STR_UI_SHORT(SilcUInt16 *)
295 #define SILC_STR_SI_SHORT(x) SILC_PARAM_SI16_SHORT, (x)
296 #define SILC_STR_UI_SHORT(x) SILC_PARAM_UI16_SHORT, (x)
298 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT
302 * #define SILC_STR_UI_INT() ...
303 * #define SILC_STR_SI_INT() ...
307 * SilcInt32/SilcUInt32.
309 * Formatting: SILC_STR_SI_INT(int)
310 * SILC_STR_UI_INT(SilcUInt32)
311 * Unformatting: SILC_STR_SI_INT(int *)
312 * SILC_STR_UI_INT(SilcUInt32 *)
315 #define SILC_STR_SI_INT(x) SILC_PARAM_SI32_INT, (x)
316 #define SILC_STR_UI_INT(x) SILC_PARAM_UI32_INT, (x)
318 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT64
322 * #define SILC_STR_UI_INT64() ...
323 * #define SILC_STR_SI_INT64() ...
327 * SilcInt64/SilcUInt64.
329 * Formatting: SILC_STR_SI_INT64(int)
330 * SILC_STR_UI_INT64(SilcUInt32)
331 * Unformatting: SILC_STR_SI_INT64(int *)
332 * SILC_STR_UI_INT64(SilcUInt32 *)
335 #define SILC_STR_SI_INT64(x) SILC_PARAM_SI64_INT, (x)
336 #define SILC_STR_UI_INT64(x) SILC_PARAM_UI64_INT, (x)
338 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_STRING
342 * #define SILC_STR_UI8_STRING() ...
343 * #define SILC_STR_UI8_STRING_ALLOC() ...
344 * #define SILC_STR_UI16_STRING() ...
345 * #define SILC_STR_UI16_STRING_ALLOC() ...
346 * #define SILC_STR_UI32_STRING() ...
347 * #define SILC_STR_UI32_STRING_ALLOC() ...
351 * Unsigned NULL terminated string. Note that the string must be
352 * NULL terminated because strlen() will be used to get the length of
355 * Formatting: SILC_STR_UI32_STRING(unsigned char *)
356 * Unformatting: SILC_STR_UI32_STRING(unsigned char **)
358 * Unformatting procedure will check for length of the string from the
359 * buffer before trying to get the string out. Thus, one *must* format the
360 * length as UI_INT or UI_SHORT into the buffer *before* formatting the
361 * actual string to the buffer, and, in unformatting one must ignore the
362 * length of the string because unformatting procedure will take it
367 * Formatting: ..., SILC_STR_UI_INT(strlen(string)),
368 * SILC_STR_UI32_STRING(string), ...
369 * Unformatting: ..., SILC_STR_UI32_STRING(&string), ...
371 * I.e., you can ignore the formatted length field in unformatting.
373 * UI8, UI16 and UI32 means that the length is considered to be
374 * either char (8 bits), short (16 bits) or int (32 bits) in
377 * _ALLOC routines automatically allocates memory for the variable sent
378 * as argument in unformatting.
381 #define SILC_STR_UI8_STRING(x) SILC_PARAM_UI8_STRING, (x)
382 #define SILC_STR_UI8_STRING_ALLOC(x) SILC_PARAM_UI8_STRING_ALLOC, (x)
383 #define SILC_STR_UI16_STRING(x) SILC_PARAM_UI16_STRING, (x)
384 #define SILC_STR_UI16_STRING_ALLOC(x) SILC_PARAM_UI16_STRING_ALLOC, (x)
385 #define SILC_STR_UI32_STRING(x) SILC_PARAM_UI32_STRING, (x)
386 #define SILC_STR_UI32_STRING_ALLOC(x) SILC_PARAM_UI32_STRING_ALLOC, (x)
388 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_NSTRING
392 * #define SILC_STR_UI8_NSTRING() ...
393 * #define SILC_STR_UI8_NSTRING_ALLOC() ...
394 * #define SILC_STR_UI16_NSTRING() ...
395 * #define SILC_STR_UI16_NSTRING_ALLOC() ...
396 * #define SILC_STR_UI32_NSTRING() ...
397 * #define SILC_STR_UI32_NSTRING_ALLOC() ...
401 * Unsigned string. Second argument is the length of the string.
403 * Formatting: SILC_STR_UI32_NSTRING(unsigned char *, SilcUInt32)
404 * Unformatting: SILC_STR_UI32_NSTRING(unsigned char **, SilcUInt32 *)
406 * Unformatting procedure will check for length of the string from the
407 * buffer before trying to get the string out. Thus, one *must* format the
408 * length as UI_INT or UI_SHORT into the buffer *before* formatting the
409 * actual string to the buffer, and, in unformatting one must ignore the
410 * length of the string because unformatting procedure will take it
415 * Formatting: ..., SILC_STR_UI_INT(strlen(string)),
416 * SILC_STR_UI32_NSTRING(string, strlen(string)), ...
417 * Unformatting: ..., SILC_STR_UI32_NSTRING(&string, &len), ...
419 * I.e., you can ignore the formatted length field in unformatting. The
420 * length taken from the buffer is returned to the pointer sent as
421 * argument (&len in above example).
423 * UI8, UI16 and UI32 means that the length is considered to be
424 * either char (8 bits), short (16 bits) or int (32 bits) in
427 * _ALLOC routines automatically allocates memory for the variable sent
428 * as argument in unformatting.
431 #define SILC_STR_UI8_NSTRING(x, l) SILC_PARAM_UI8_NSTRING, (x), (l)
432 #define SILC_STR_UI8_NSTRING_ALLOC(x, l) \
433 SILC_PARAM_UI8_NSTRING_ALLOC, (x), (l)
434 #define SILC_STR_UI16_NSTRING(x, l) SILC_PARAM_UI16_NSTRING, (x), (l)
435 #define SILC_STR_UI16_NSTRING_ALLOC(x, l) \
436 SILC_PARAM_UI16_NSTRING_ALLOC, (x), (l)
437 #define SILC_STR_UI32_NSTRING(x, l) SILC_PARAM_UI32_NSTRING, (x), (l)
438 #define SILC_STR_UI32_NSTRING_ALLOC(x, l) \
439 SILC_PARAM_UI32_NSTRING_ALLOC, (x), (l)
441 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA
445 * #define SILC_STR_DATA() ...
446 * #define SILC_STR_DATA_ALLOC() ...
450 * Binary data formatting. Second argument is the length of the data.
452 * Formatting: SILC_STR_DATA(unsigned char *, SilcUInt32)
453 * Unformatting: SILC_STR_DATA(unsigned char **, SilcUInt32)
455 * This type can be used to take arbitrary size data block from the buffer
456 * by sending the requested amount of bytes as argument.
458 * _ALLOC routines automatically allocates memory for the variable sent
459 * as argument in unformatting.
462 #define SILC_STR_DATA(x, l) SILC_PARAM_DATA, (x), (l)
463 #define SILC_STR_DATA_ALLOC(x, l) SILC_PARAM_DATA_ALLOC, (x), (l)
466 #define SILC_STR_UI_XNSTRING(x, l) SILC_PARAM_UI_XNSTRING, (x), (l)
467 #define SILC_STR_UI_XNSTRING_ALLOC(x, l) SILC_PARAM_UI_XNSTRING_ALLOC, (x), (l)
469 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_BUFFER
473 * #define SILC_STR_BUFFER() ...
474 * #define SILC_STR_BUFFER_ALLOC() ...
478 * SilcBuffer formatting.
480 * Formatting: SILC_STR_DATA(SilcBuffer)
481 * Unformatting: SILC_STR_DATA(SilcBuffer)
483 * This type can be used to format and unformat SilcBuffer. The lenght
484 * of the buffer will be automatically encoded into the buffer as a 32-bit
485 * integer. In unformatting the SilcBuffer context must be pre-allocated.
487 * _ALLOC routines automatically allocates memory inside SilcBuffer in
491 #define SILC_STR_BUFFER(x) SILC_BUFFER_DATA, (x)
492 #define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER_ALLOC, (x)
494 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET
498 * #define SILC_STR_OFFSET() ...
502 * Offset in buffer. This can be used in formatting and unformatting to
503 * move the data pointer of the buffer either forwards (positive offset)
504 * or backwards (negative offset). It can be used to for example skip
505 * some types during unformatting.
509 * ..., SILC_STR_OFFSET(5), ...
510 * ..., SILC_STR_OFFSET(-3), ...
512 * Moves the data pointer at the point of the offset either forward
513 * or backward and then moves to the next type. Multiple SILC_STR_OFFSETs
514 * can be used in formatting and unformatting at the same time.
517 #define SILC_STR_OFFSET(x) SILC_PARAM_OFFSET, (x)
519 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE
523 * #define SILC_STR_ADVANCE ...
527 * Advance the buffer to the end of the data after the formatting is
528 * done. In normal operation when the formatted data is written the
529 * buffer is located at the start of the data. With SILC_STR_ADVANCE
530 * the buffer will be located at the end of the data. This makes it
531 * easy to add new data immediately after the previously added data.
536 * len = read(fd, buf, sizeof(buf));
538 * // Add read data to the buffer
539 * silc_buffer_format(buffer,
541 * SILC_STR_UI_XNSTRING(buf, len),
545 * // Move to beginning of buffer
546 * silc_buffer_push(buffer, silc_buffer_truelen(buffer));
549 #define SILC_STR_ADVANCE SILC_PARAM_ADVANCE
551 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_END
555 * #define SILC_STR_END ...
559 * Marks end of the argument list. This must be at the end of the
560 * argument list or error will occur.
563 #define SILC_STR_END SILC_PARAM_END
565 /****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END
569 * #define SILC_STRFMT_END ...
573 * Marks end of the argument list in silc_buffer_strformat function.
574 * This must be at the end of the argument list or error will occur.
577 #define SILC_STRFMT_END (void *)SILC_STR_END
579 #endif /* !SILCBUFFMT_H */