silc_buffer_sstrformat to preserve buffer locations.
[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 a few functions for formatting
25  * various different data types into a buffer, and retrieving
26  * various data from buffer into specific data types.  It is usefull
27  * to format for example packets and later unformat them.
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 /* Macros for expanding parameters into variable function argument list.
206    These are passed to silc_buffer_format and silc_buffer_unformat
207    functions. */
208
209 /* Buffer parameter types.
210
211    _SI_ = signed
212    _UI_ = unsigned
213
214   Any XXX_STRING_ALLOC types will allocate space for the data and
215   memcpy the data to the pointer sent as argument (in unformatting).
216
217   Any XXX_STRING will not allocate or copy any data.  Instead it
218   will set the pointer to the data.  Note that the data pointer
219   returned (in unformatting) must not be freed.
220
221 */
222 typedef enum {
223   SILC_BUFFER_PARAM_SI8_CHAR,
224   SILC_BUFFER_PARAM_UI8_CHAR,
225
226   SILC_BUFFER_PARAM_SI16_SHORT,
227   SILC_BUFFER_PARAM_UI16_SHORT,
228
229   SILC_BUFFER_PARAM_SI32_INT,
230   SILC_BUFFER_PARAM_UI32_INT,
231
232   SILC_BUFFER_PARAM_SI64_INT,
233   SILC_BUFFER_PARAM_UI64_INT,
234
235   SILC_BUFFER_PARAM_UI8_STRING,         /* No copy */
236   SILC_BUFFER_PARAM_UI8_STRING_ALLOC,   /* Alloc + memcpy */
237   SILC_BUFFER_PARAM_UI16_STRING,        /* No copy */
238   SILC_BUFFER_PARAM_UI16_STRING_ALLOC,  /* Alloc + memcpy */
239   SILC_BUFFER_PARAM_UI32_STRING,        /* No copy */
240   SILC_BUFFER_PARAM_UI32_STRING_ALLOC,  /* Alloc + memcpy */
241   SILC_BUFFER_PARAM_UI8_NSTRING,        /* No copy */
242   SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC,  /* Alloc + memcpy */
243   SILC_BUFFER_PARAM_UI16_NSTRING,       /* No copy */
244   SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC, /* Alloc + memcpy */
245   SILC_BUFFER_PARAM_UI32_NSTRING,       /* No copy */
246   SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC, /* Alloc + memcpy */
247   SILC_BUFFER_PARAM_UI_XNSTRING,        /* No copy */
248   SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC,  /* Alloc + memcpy */
249   SILC_BUFFER_PARAM_DATA,               /* No copy */
250   SILC_BUFFER_PARAM_DATA_ALLOC,         /* Alloc + memcpy */
251
252   SILC_BUFFER_PARAM_OFFSET,
253   SILC_BUFFER_PARAM_ADVANCE,
254
255   SILC_BUFFER_PARAM_END
256 } SilcBufferParamType;
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_BUFFER_PARAM_SI8_CHAR, (x)
276 #define SILC_STR_UI_CHAR(x) SILC_BUFFER_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  *    Signed/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_BUFFER_PARAM_SI16_SHORT, (x)
296 #define SILC_STR_UI_SHORT(x) SILC_BUFFER_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  *    Signed/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_BUFFER_PARAM_SI32_INT, (x)
316 #define SILC_STR_UI_INT(x) SILC_BUFFER_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  *    Signed/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_BUFFER_PARAM_SI64_INT, (x)
336 #define SILC_STR_UI_INT64(x) SILC_BUFFER_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_BUFFER_PARAM_UI8_STRING, (x)
382 #define SILC_STR_UI8_STRING_ALLOC(x) SILC_BUFFER_PARAM_UI8_STRING_ALLOC, (x)
383 #define SILC_STR_UI16_STRING(x) SILC_BUFFER_PARAM_UI16_STRING, (x)
384 #define SILC_STR_UI16_STRING_ALLOC(x) SILC_BUFFER_PARAM_UI16_STRING_ALLOC, (x)
385 #define SILC_STR_UI32_STRING(x) SILC_BUFFER_PARAM_UI32_STRING, (x)
386 #define SILC_STR_UI32_STRING_ALLOC(x) SILC_BUFFER_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_BUFFER_PARAM_UI8_NSTRING, (x), (l)
432 #define SILC_STR_UI8_NSTRING_ALLOC(x, l) \
433   SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC, (x), (l)
434 #define SILC_STR_UI16_NSTRING(x, l) SILC_BUFFER_PARAM_UI16_NSTRING, (x), (l)
435 #define SILC_STR_UI16_NSTRING_ALLOC(x, l) \
436   SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC, (x), (l)
437 #define SILC_STR_UI32_NSTRING(x, l) SILC_BUFFER_PARAM_UI32_NSTRING, (x), (l)
438 #define SILC_STR_UI32_NSTRING_ALLOC(x, l) \
439   SILC_BUFFER_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 lenght 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_BUFFER_PARAM_DATA, (x), (l)
463 #define SILC_STR_DATA_ALLOC(x, l) \
464   SILC_BUFFER_PARAM_DATA_ALLOC, (x), (l)
465
466 /* Deprecated */
467 #define SILC_STR_UI_XNSTRING(x, l) SILC_BUFFER_PARAM_UI_XNSTRING, (x), (l)
468 #define SILC_STR_UI_XNSTRING_ALLOC(x, l) \
469   SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC, (x), (l)
470
471 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_OFFSET
472  *
473  * NAME
474  *
475  *    #define SILC_STR_OFFSET() ...
476  *
477  * DESCRIPTION
478  *
479  *    Offset in buffer.  This can be used in formatting and unformatting to
480  *    move the data pointer of the buffer either forwards (positive offset)
481  *    or backwards (negative offset).  It can be used to for example skip
482  *    some types during unformatting.
483  *
484  *    Example:
485  *
486  *    ..., SILC_STR_OFFSET(5), ...
487  *    ..., SILC_STR_OFFSET(-3), ...
488  *
489  *    Moves the data pointer at the point of the offset either forward
490  *    or backward and then moves to the next type.  Multiple SILC_STR_OFFSETs
491  *    can be used in formatting and unformatting at the same time.
492  *
493  ***/
494 #define SILC_STR_OFFSET(x) SILC_BUFFER_PARAM_OFFSET, (x)
495
496 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_ADVANCE
497  *
498  * NAME
499  *
500  *    #define SILC_STR_ADVANCE ...
501  *
502  * DESCRIPTION
503  *
504  *    Advance the buffer to the end of the data after the formatting is
505  *    done.  In normal operation when the formatted data is written the
506  *    buffer is located at the start of the data.  With SILC_STR_ADVANCE
507  *    the buffer will be located at the end of the data.  This makes it
508  *    easy to add new data immediately after the previously added data.
509  *
510  * EXAMPLE
511  *
512  *    do {
513  *      len = read(fd, buf, sizeof(buf));
514  *      if (len > 0)
515  *        // Add read data to the buffer
516  *        silc_buffer_format(buffer,
517  *                           SILC_STR_ADVANCE,
518  *                           SILC_STR_UI_XNSTRING(buf, len),
519  *                           SILC_STR_END);
520  *    } while (len > 0);
521  *
522  *    // Move to beginning of buffer
523  *    silc_buffer_push(buffer, silc_buffer_truelen(buffer));
524  *
525  ***/
526 #define SILC_STR_ADVANCE SILC_BUFFER_PARAM_ADVANCE
527
528 /****d* silcutil/SilcBufferFormatAPI/SILC_STR_END
529  *
530  * NAME
531  *
532  *    #define SILC_STR_END ...
533  *
534  * DESCRIPTION
535  *
536  *    Marks end of the argument list. This must be at the end of the
537  *    argument list or error will occur.
538  *
539  ***/
540 #define SILC_STR_END SILC_BUFFER_PARAM_END
541
542 /****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END
543  *
544  * NAME
545  *
546  *    #define SILC_STRFMT_END ...
547  *
548  * DESCRIPTION
549  *
550  *    Marks end of the argument list in silc_buffer_strformat function.
551  *    This must be at the end of the argument list or error will occur.
552  *
553  ***/
554 #define SILC_STRFMT_END (void *)SILC_STR_END
555
556 #endif  /* !SILCBUFFMT_H */