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.
23 /* Macros to check whether there is enough free space to add the
24 required amount of data. For unformatting this means that there must
25 be the data that is to be extracted. */
26 #define FORMAT_HAS_SPACE(__x__, __req__) \
28 if (__req__ > silc_buffer_len((__x__))) \
31 #define UNFORMAT_HAS_SPACE(__x__, __req__) \
33 if (__req__ > silc_buffer_len((__x__))) \
35 if ((__req__ + 1) <= 0) \
39 /* Formats the arguments sent and puts them into the buffer sent as
40 argument. The buffer must be initialized beforehand and it must have
41 enough free space to include the formatted data. If this function
42 fails caller should not trust the buffer anymore and should free it.
43 This function is used, for example, to create packets to send over
46 int silc_buffer_format(SilcBuffer dst, ...)
52 ret = silc_buffer_format_vp(dst, ap);
58 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
60 SilcBufferParamType fmt;
61 unsigned char *start_ptr = dst->data;
64 /* Parse the arguments by formatting type. */
66 fmt = va_arg(ap, SilcBufferParamType);
69 case SILC_BUFFER_PARAM_OFFSET:
71 int offst = va_arg(ap, int);
75 FORMAT_HAS_SPACE(dst, offst);
76 silc_buffer_pull(dst, offst);
78 silc_buffer_push(dst, -(offst));
82 case SILC_BUFFER_PARAM_SI8_CHAR:
84 char x = (char)va_arg(ap, int);
85 FORMAT_HAS_SPACE(dst, 1);
86 silc_buffer_put(dst, &x, 1);
87 silc_buffer_pull(dst, 1);
90 case SILC_BUFFER_PARAM_UI8_CHAR:
92 unsigned char x = (unsigned char)va_arg(ap, int);
93 FORMAT_HAS_SPACE(dst, 1);
94 silc_buffer_put(dst, &x, 1);
95 silc_buffer_pull(dst, 1);
98 case SILC_BUFFER_PARAM_SI16_SHORT:
101 SilcInt16 x = (SilcInt16)va_arg(ap, int);
102 FORMAT_HAS_SPACE(dst, 2);
103 SILC_PUT16_MSB(x, xf);
104 silc_buffer_put(dst, xf, 2);
105 silc_buffer_pull(dst, 2);
108 case SILC_BUFFER_PARAM_UI16_SHORT:
111 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
112 FORMAT_HAS_SPACE(dst, 2);
113 SILC_PUT16_MSB(x, xf);
114 silc_buffer_put(dst, xf, 2);
115 silc_buffer_pull(dst, 2);
118 case SILC_BUFFER_PARAM_SI32_INT:
121 SilcInt32 x = va_arg(ap, SilcInt32);
122 FORMAT_HAS_SPACE(dst, 4);
123 SILC_PUT32_MSB(x, xf);
124 silc_buffer_put(dst, xf, 4);
125 silc_buffer_pull(dst, 4);
128 case SILC_BUFFER_PARAM_UI32_INT:
131 SilcUInt32 x = va_arg(ap, SilcUInt32);
132 FORMAT_HAS_SPACE(dst, 4);
133 SILC_PUT32_MSB(x, xf);
134 silc_buffer_put(dst, xf, 4);
135 silc_buffer_pull(dst, 4);
138 case SILC_BUFFER_PARAM_SI64_INT:
141 SilcInt64 x = va_arg(ap, SilcInt64);
142 FORMAT_HAS_SPACE(dst, sizeof(SilcInt64));
143 SILC_PUT64_MSB(x, xf);
144 silc_buffer_put(dst, xf, sizeof(SilcInt64));
145 silc_buffer_pull(dst, sizeof(SilcInt64));
148 case SILC_BUFFER_PARAM_UI64_INT:
151 SilcUInt64 x = va_arg(ap, SilcUInt64);
152 FORMAT_HAS_SPACE(dst, sizeof(SilcUInt64));
153 SILC_PUT64_MSB(x, xf);
154 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
155 silc_buffer_pull(dst, sizeof(SilcUInt64));
158 case SILC_BUFFER_PARAM_UI8_STRING:
159 case SILC_BUFFER_PARAM_UI16_STRING:
160 case SILC_BUFFER_PARAM_UI32_STRING:
161 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
162 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
163 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
165 unsigned char *x = va_arg(ap, unsigned char *);
166 SilcUInt32 tmp_len = strlen(x);
167 FORMAT_HAS_SPACE(dst, tmp_len);
168 silc_buffer_put(dst, x, tmp_len);
169 silc_buffer_pull(dst, tmp_len);
172 case SILC_BUFFER_PARAM_UI8_NSTRING:
173 case SILC_BUFFER_PARAM_UI16_NSTRING:
174 case SILC_BUFFER_PARAM_UI32_NSTRING:
175 case SILC_BUFFER_PARAM_UI_XNSTRING:
176 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
177 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
178 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
179 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
181 unsigned char *x = va_arg(ap, unsigned char *);
182 SilcUInt32 len = va_arg(ap, SilcUInt32);
184 FORMAT_HAS_SPACE(dst, len);
185 silc_buffer_put(dst, x, len);
186 silc_buffer_pull(dst, len);
190 case SILC_BUFFER_PARAM_END:
194 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
195 "format the data.", fmt));
202 SILC_LOG_DEBUG(("Error occured while formatting data"));
203 len = dst->data - start_ptr;
204 silc_buffer_push(dst, len);
208 /* Push the buffer back to where it belongs. */
209 len = dst->data - start_ptr;
210 silc_buffer_push(dst, len);
214 /* Unformats the buffer sent as argument. The unformatted data is returned
215 to the variable argument list of pointers. The buffer must point to the
216 start of the data area to be unformatted. Buffer maybe be safely free'd
217 after this returns succesfully. */
219 int silc_buffer_unformat(SilcBuffer src, ...)
225 ret = silc_buffer_unformat_vp(src, ap);
231 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
233 SilcBufferParamType fmt;
234 unsigned char *start_ptr = src->data;
237 /* Parse the arguments by formatting type. */
239 fmt = va_arg(ap, SilcBufferParamType);
242 case SILC_BUFFER_PARAM_OFFSET:
244 int offst = va_arg(ap, int);
248 UNFORMAT_HAS_SPACE(src, offst);
249 silc_buffer_pull(src, offst);
251 silc_buffer_push(src, -(offst));
255 case SILC_BUFFER_PARAM_SI8_CHAR:
257 char *x = va_arg(ap, char *);
258 UNFORMAT_HAS_SPACE(src, 1);
261 silc_buffer_pull(src, 1);
264 case SILC_BUFFER_PARAM_UI8_CHAR:
266 unsigned char *x = va_arg(ap, unsigned char *);
267 UNFORMAT_HAS_SPACE(src, 1);
270 silc_buffer_pull(src, 1);
273 case SILC_BUFFER_PARAM_SI16_SHORT:
275 SilcInt16 *x = va_arg(ap, SilcInt16 *);
276 UNFORMAT_HAS_SPACE(src, 2);
278 SILC_GET16_MSB(*x, src->data);
279 silc_buffer_pull(src, 2);
282 case SILC_BUFFER_PARAM_UI16_SHORT:
284 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
285 UNFORMAT_HAS_SPACE(src, 2);
287 SILC_GET16_MSB(*x, src->data);
288 silc_buffer_pull(src, 2);
291 case SILC_BUFFER_PARAM_SI32_INT:
293 SilcInt32 *x = va_arg(ap, SilcInt32 *);
294 UNFORMAT_HAS_SPACE(src, 4);
296 SILC_GET32_MSB(*x, src->data);
297 silc_buffer_pull(src, 4);
300 case SILC_BUFFER_PARAM_UI32_INT:
302 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
303 UNFORMAT_HAS_SPACE(src, 4);
305 SILC_GET32_MSB(*x, src->data);
306 silc_buffer_pull(src, 4);
309 case SILC_BUFFER_PARAM_SI64_INT:
311 SilcInt64 *x = va_arg(ap, SilcInt64 *);
312 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
314 SILC_GET64_MSB(*x, src->data);
315 silc_buffer_pull(src, sizeof(SilcInt64));
318 case SILC_BUFFER_PARAM_UI64_INT:
320 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
321 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
323 SILC_GET64_MSB(*x, src->data);
324 silc_buffer_pull(src, sizeof(SilcUInt64));
327 case SILC_BUFFER_PARAM_UI8_STRING:
330 unsigned char **x = va_arg(ap, unsigned char **);
331 UNFORMAT_HAS_SPACE(src, 1);
332 len2 = (SilcUInt8)src->data[0];
333 silc_buffer_pull(src, 1);
334 UNFORMAT_HAS_SPACE(src, len2);
337 silc_buffer_pull(src, len2);
340 case SILC_BUFFER_PARAM_UI16_STRING:
343 unsigned char **x = va_arg(ap, unsigned char **);
344 UNFORMAT_HAS_SPACE(src, 2);
345 SILC_GET16_MSB(len2, src->data);
346 silc_buffer_pull(src, 2);
347 UNFORMAT_HAS_SPACE(src, len2);
350 silc_buffer_pull(src, len2);
353 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
356 unsigned char **x = va_arg(ap, unsigned char **);
357 UNFORMAT_HAS_SPACE(src, 1);
358 len2 = (SilcUInt8)src->data[0];
359 silc_buffer_pull(src, 1);
360 UNFORMAT_HAS_SPACE(src, len2);
362 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
363 memcpy(*x, src->data, len2);
365 silc_buffer_pull(src, len2);
368 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
371 unsigned char **x = va_arg(ap, unsigned char **);
372 UNFORMAT_HAS_SPACE(src, 2);
373 SILC_GET16_MSB(len2, src->data);
374 silc_buffer_pull(src, 2);
375 UNFORMAT_HAS_SPACE(src, len2);
377 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
378 memcpy(*x, src->data, len2);
380 silc_buffer_pull(src, len2);
383 case SILC_BUFFER_PARAM_UI32_STRING:
386 unsigned char **x = va_arg(ap, unsigned char **);
387 UNFORMAT_HAS_SPACE(src, 4);
388 SILC_GET32_MSB(len2, src->data);
389 silc_buffer_pull(src, 4);
390 UNFORMAT_HAS_SPACE(src, len2);
393 silc_buffer_pull(src, len2);
396 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
399 unsigned char **x = va_arg(ap, unsigned char **);
400 UNFORMAT_HAS_SPACE(src, 4);
401 SILC_GET32_MSB(len2, src->data);
402 silc_buffer_pull(src, 4);
403 UNFORMAT_HAS_SPACE(src, len2);
405 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
406 memcpy(*x, src->data, len2);
408 silc_buffer_pull(src, len2);
411 case SILC_BUFFER_PARAM_UI8_NSTRING:
414 unsigned char **x = va_arg(ap, unsigned char **);
415 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
416 UNFORMAT_HAS_SPACE(src, 1);
417 len2 = (SilcUInt8)src->data[0];
418 silc_buffer_pull(src, 1);
419 UNFORMAT_HAS_SPACE(src, len2);
424 silc_buffer_pull(src, len2);
427 case SILC_BUFFER_PARAM_UI16_NSTRING:
430 unsigned char **x = va_arg(ap, unsigned char **);
431 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
432 UNFORMAT_HAS_SPACE(src, 2);
433 SILC_GET16_MSB(len2, src->data);
434 silc_buffer_pull(src, 2);
435 UNFORMAT_HAS_SPACE(src, len2);
440 silc_buffer_pull(src, len2);
443 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
446 unsigned char **x = va_arg(ap, unsigned char **);
447 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
448 UNFORMAT_HAS_SPACE(src, 1);
449 len2 = (SilcUInt8)src->data[0];
450 silc_buffer_pull(src, 1);
451 UNFORMAT_HAS_SPACE(src, len2);
455 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
456 memcpy(*x, src->data, len2);
458 silc_buffer_pull(src, len2);
461 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
464 unsigned char **x = va_arg(ap, unsigned char **);
465 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
466 UNFORMAT_HAS_SPACE(src, 2);
467 SILC_GET16_MSB(len2, src->data);
468 silc_buffer_pull(src, 2);
469 UNFORMAT_HAS_SPACE(src, len2);
473 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
474 memcpy(*x, src->data, len2);
476 silc_buffer_pull(src, len2);
479 case SILC_BUFFER_PARAM_UI32_NSTRING:
482 unsigned char **x = va_arg(ap, unsigned char **);
483 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
484 UNFORMAT_HAS_SPACE(src, 4);
485 SILC_GET32_MSB(len2, src->data);
486 silc_buffer_pull(src, 4);
487 UNFORMAT_HAS_SPACE(src, len2);
492 silc_buffer_pull(src, len2);
495 case SILC_BUFFER_PARAM_UI_XNSTRING:
497 unsigned char **x = va_arg(ap, unsigned char **);
498 SilcUInt32 len = va_arg(ap, SilcUInt32);
499 UNFORMAT_HAS_SPACE(src, len);
502 silc_buffer_pull(src, len);
505 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
507 unsigned char **x = va_arg(ap, unsigned char **);
508 SilcUInt32 len = va_arg(ap, SilcUInt32);
509 UNFORMAT_HAS_SPACE(src, len);
511 *x = silc_calloc(len + 1, sizeof(unsigned char));
512 memcpy(*x, src->data, len);
514 silc_buffer_pull(src, len);
517 case SILC_BUFFER_PARAM_END:
521 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
522 "format the data.", fmt));
529 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
530 len = src->data - start_ptr;
531 silc_buffer_push(src, len);
535 /* Push the buffer back to the start. */
536 len = src->data - start_ptr;
537 silc_buffer_push(src, len);
541 /* Formats strings into a buffer */
543 int silc_buffer_strformat(SilcBuffer dst, ...)
545 int len = silc_buffer_truelen(dst);
550 /* Parse the arguments by formatting type. */
552 char *string = va_arg(va, char *);
558 if (string == (char *)SILC_BUFFER_PARAM_END)
561 slen = strlen(string);
562 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
566 memcpy(dst->head + len, string, slen);
568 dst->head[len] = '\0';
571 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
576 dst->end = dst->head + len;
577 dst->data = dst->head;
578 dst->tail = dst->end;
584 /* Formats strings into a buffer. Allocates memory from SilcStack. */
586 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
588 int len = silc_buffer_truelen(dst);
593 /* Parse the arguments by formatting type. */
595 char *string = va_arg(va, char *);
601 if (string == (char *)SILC_BUFFER_PARAM_END)
604 slen = strlen(string);
605 d = silc_srealloc_ua(stack, len + 1, dst->head,
606 sizeof(*dst->head) * (slen + len + 1));
610 memcpy(dst->head + len, string, slen);
612 dst->head[len] = '\0';
615 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
620 dst->end = dst->head + len;
621 dst->data = dst->head;
622 dst->tail = dst->end;