Added SILC_STR_BUFFER to format SilcBuffer.
[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  ***/
30
31 #ifndef SILCBUFFMT_H
32 #define SILCBUFFMT_H
33
34 /* Prototypes */
35
36 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format
37  *
38  * SYNOPSIS
39  *
40  *    int silc_buffer_format(SilcBuffer dst, ...);
41  *
42  * DESCRIPTION
43  *
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
47  *    enough space.
48  *
49  * EXAMPLE
50  *
51  *    SilcBufferStruct buffer;
52  *    SilcBuffer buf;
53  *
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),
61  *                             SILC_STR_END);
62  *    if (ret < 0)
63  *      error;
64  *
65  *    // Free the allocated data
66  *    silc_buffer_purge(&buffer);
67  *
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),
73  *                             SILC_STR_END);
74  *
75  *    // Free the allocated buffer
76  *    silc_buffer_free(buf);
77  *
78  ***/
79 int silc_buffer_format(SilcBuffer dst, ...);
80
81 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sformat
82  *
83  * SYNOPSIS
84  *
85  *    int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
86  *
87  * DESCRIPTION
88  *
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.
91  *
92  ***/
93 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...);
94
95 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
96  *
97  * SYNOPSIS
98  *
99  *    int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
100  *
101  * DESCRIPTION
102  *
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.
105  *
106  ***/
107 int silc_buffer_format_vp(SilcBuffer dst, va_list ap);
108
109 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_format_vp
110  *
111  * SYNOPSIS
112  *
113  *    int silc_buffer_format_vp(SilcBuffer dst, va_list vp);
114  *
115  * DESCRIPTION
116  *
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.
119  *
120  ***/
121 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap);
122
123 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat
124  *
125  * SYNOPSIS
126  *
127  *    int silc_buffer_unformat(SilcBuffer src, ...);
128  *
129  * DESCRIPTION
130  *
131  *    Unformats a buffer from a variable argument list.  Returns -1 on error
132  *    and the length of the unformatted buffer otherwise.
133  *
134  * EXAMPLE
135  *
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),
141  *                               SILC_STR_END);
142  *    if (ret < 0)
143  *      error;
144  *
145  ***/
146 int silc_buffer_unformat(SilcBuffer src, ...);
147
148 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_unformat_vp
149  *
150  * SYNOPSIS
151  *
152  *    int silc_buffer_unformat_vp(SilcBuffer src, va_list vp);
153  *
154  * DESCRIPTION
155  *
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.
158  *
159  ***/
160 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap);
161
162 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_strformat
163  *
164  * SYNOPSIS
165  *
166  *   int silc_buffer_strformat(SilcBuffer dst, ...);
167  *
168  * DESCRIPTION
169  *
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.
176  *
177  * EXAMPLE
178  *
179  *    ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STRFMT_END);
180  *    if (ret < 0)
181  *      error;
182  *
183  ***/
184 int silc_buffer_strformat(SilcBuffer dst, ...);
185
186 /****f* silcutil/SilcBufferFormatAPI/silc_buffer_sstrformat
187  *
188  * SYNOPSIS
189  *
190  *   int silc_buffer_strformat(SilcStack stack, SilcBuffer dst, ...);
191  *
192  * DESCRIPTION
193  *
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'.
201  *
202  ***/
203 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...);
204
205 /****d* silcutil/SilcBufferFormatAPI/SilcBufferParamType
206  *
207  * NAME
208  *
209  *    typedef enum { ... } SilcBufferParamType;
210  *
211  * DESCRIPTION
212  *
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.
217  *
218  * SOURCE
219  */
220 typedef enum {
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 */
233
234   /* Internal types */
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 */
247
248   SILC_PARAM_OFFSET,
249   SILC_PARAM_ADVANCE,
250
251   SILC_PARAM_UI_XNSTRING,
252   SILC_PARAM_UI_XNSTRING_ALLOC,
253
254   SILC_PARAM_END
255 } SilcBufferParamType;
256 /***/
257
258 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_CHAR
259  *
260  * NAME
261  *
262  *    #define SILC_STR_UI_CHAR() ...
263  *    #define SILC_STR_SI_CHAR() ...
264  *
265  * DESCRIPTION
266  *
267  *    One signed/unsigned character.
268  *
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 *)
273  *
274  ***/
275 #define SILC_STR_SI_CHAR(x) SILC_PARAM_SI8_CHAR, (x)
276 #define SILC_STR_UI_CHAR(x) SILC_PARAM_UI8_CHAR, (x)
277
278 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_SHORT
279  *
280  * NAME
281  *
282  *    #define SILC_STR_UI_SHORT() ...
283  *    #define SILC_STR_SI_SHORT() ...
284  *
285  * DESCRIPTION
286  *
287  *    SilcInt16/SilcUInt16.
288  *
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 *)
293  *
294  ***/
295 #define SILC_STR_SI_SHORT(x) SILC_PARAM_SI16_SHORT, (x)
296 #define SILC_STR_UI_SHORT(x) SILC_PARAM_UI16_SHORT, (x)
297
298 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT
299  *
300  * NAME
301  *
302  *    #define SILC_STR_UI_INT() ...
303  *    #define SILC_STR_SI_INT() ...
304  *
305  * DESCRIPTION
306  *
307  *    SilcInt32/SilcUInt32.
308  *
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 *)
313  *
314  ***/
315 #define SILC_STR_SI_INT(x) SILC_PARAM_SI32_INT, (x)
316 #define SILC_STR_UI_INT(x) SILC_PARAM_UI32_INT, (x)
317
318 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_INT64
319  *
320  * NAME
321  *
322  *    #define SILC_STR_UI_INT64() ...
323  *    #define SILC_STR_SI_INT64() ...
324  *
325  * DESCRIPTION
326  *
327  *    SilcInt64/SilcUInt64.
328  *
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 *)
333  *
334  ***/
335 #define SILC_STR_SI_INT64(x) SILC_PARAM_SI64_INT, (x)
336 #define SILC_STR_UI_INT64(x) SILC_PARAM_UI64_INT, (x)
337
338 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_STRING
339  *
340  * NAME
341  *
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() ...
348  *
349  * DESCRIPTION
350  *
351  *    Unsigned NULL terminated string. Note that the string must be
352  *    NULL terminated because strlen() will be used to get the length of
353  *    the string.
354  *
355  *    Formatting:    SILC_STR_UI32_STRING(unsigned char *)
356  *    Unformatting:  SILC_STR_UI32_STRING(unsigned char **)
357  *
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
363  *    automatically.
364  *
365  *    Example:
366  *
367  *    Formatting:    ..., SILC_STR_UI_INT(strlen(string)),
368  *                        SILC_STR_UI32_STRING(string), ...
369  *    Unformatting:  ..., SILC_STR_UI32_STRING(&string), ...
370  *
371  *    I.e., you can ignore the formatted length field in unformatting.
372  *
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
375  *    unformatting.
376  *
377  *    _ALLOC routines automatically allocates memory for the variable sent
378  *    as argument in unformatting.
379  *
380  ***/
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)
387
388 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_*_NSTRING
389  *
390  * NAME
391  *
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() ...
398  *
399  * DESCRIPTION
400  *
401  *    Unsigned string. Second argument is the length of the string.
402  *
403  *    Formatting:    SILC_STR_UI32_NSTRING(unsigned char *, SilcUInt32)
404  *    Unformatting:  SILC_STR_UI32_NSTRING(unsigned char **, SilcUInt32 *)
405  *
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
411  *    automatically.
412  *
413  *     Example:
414  *
415  *     Formatting:    ..., SILC_STR_UI_INT(strlen(string)),
416  *                         SILC_STR_UI32_NSTRING(string, strlen(string)), ...
417  *     Unformatting:  ..., SILC_STR_UI32_NSTRING(&string, &len), ...
418  *
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).
422  *
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
425  *    unformatting.
426  *
427  *    _ALLOC routines automatically allocates memory for the variable sent
428  *    as argument in unformatting.
429  *
430  ***/
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)
440
441 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_DATA
442  *
443  * NAME
444  *
445  *    #define SILC_STR_DATA() ...
446  *    #define SILC_STR_DATA_ALLOC() ...
447  *
448  * DESCRIPTION
449  *
450  *    Binary data formatting.  Second argument is the length of the data.
451  *
452  *    Formatting:    SILC_STR_DATA(unsigned char *, SilcUInt32)
453  *    Unformatting:  SILC_STR_DATA(unsigned char **, SilcUInt32)
454  *
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.
457  *
458  *    _ALLOC routines automatically allocates memory for the variable sent
459  *    as argument in unformatting.
460  *
461  ***/
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)
464
465 /* Deprecated */
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)
468
469 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_BUFFER
470  *
471  * NAME
472  *
473  *    #define SILC_STR_BUFFER() ...
474  *    #define SILC_STR_BUFFER_ALLOC() ...
475  *
476  * DESCRIPTION
477  *
478  *    SilcBuffer formatting.
479  *
480  *    Formatting:    SILC_STR_DATA(SilcBuffer)
481  *    Unformatting:  SILC_STR_DATA(SilcBuffer)
482  *
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.
486  *
487  *    _ALLOC routines automatically allocates memory inside SilcBuffer in
488  *    unformatting.
489  *
490  ***/
491 #define SILC_STR_BUFFER(x) SILC_BUFFER_DATA, (x)
492 #define SILC_STR_BUFFER_ALLOC(x) SILC_PARAM_BUFFER_ALLOC, (x)
493
494 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET
495  *
496  * NAME
497  *
498  *    #define SILC_STR_OFFSET() ...
499  *
500  * DESCRIPTION
501  *
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.
506  *
507  *    Example:
508  *
509  *    ..., SILC_STR_OFFSET(5), ...
510  *    ..., SILC_STR_OFFSET(-3), ...
511  *
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.
515  *
516  ***/
517 #define SILC_STR_OFFSET(x) SILC_PARAM_OFFSET, (x)
518
519 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE
520  *
521  * NAME
522  *
523  *    #define SILC_STR_ADVANCE ...
524  *
525  * DESCRIPTION
526  *
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.
532  *
533  * EXAMPLE
534  *
535  *    do {
536  *      len = read(fd, buf, sizeof(buf));
537  *      if (len > 0)
538  *        // Add read data to the buffer
539  *        silc_buffer_format(buffer,
540  *                           SILC_STR_ADVANCE,
541  *                           SILC_STR_UI_XNSTRING(buf, len),
542  *                           SILC_STR_END);
543  *    } while (len > 0);
544  *
545  *    // Move to beginning of buffer
546  *    silc_buffer_push(buffer, silc_buffer_truelen(buffer));
547  *
548  ***/
549 #define SILC_STR_ADVANCE SILC_PARAM_ADVANCE
550
551 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_END
552  *
553  * NAME
554  *
555  *    #define SILC_STR_END ...
556  *
557  * DESCRIPTION
558  *
559  *    Marks end of the argument list. This must be at the end of the
560  *    argument list or error will occur.
561  *
562  ***/
563 #define SILC_STR_END SILC_PARAM_END
564
565 /****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END
566  *
567  * NAME
568  *
569  *    #define SILC_STRFMT_END ...
570  *
571  * DESCRIPTION
572  *
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.
575  *
576  ***/
577 #define SILC_STRFMT_END (void *)SILC_STR_END
578
579 #endif  /* !SILCBUFFMT_H */