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 /************************** Types and definitions ***************************/
25 /* Check that buffer has enough room to format data in it, if not
27 #define FORMAT_HAS_SPACE(s, b, req) \
29 if (!silc_buffer_senlarge(s, b, req)) \
34 /* Check that there is data to be unformatted */
35 #define UNFORMAT_HAS_SPACE(b, req) \
37 if (req > silc_buffer_len(b)) \
44 /******************************* Formatting *********************************/
46 int silc_buffer_format(SilcBuffer dst, ...)
52 ret = silc_buffer_sformat_vp(NULL, dst, ap);
58 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
60 return silc_buffer_sformat_vp(NULL, dst, ap);
63 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
69 ret = silc_buffer_sformat_vp(stack, dst, ap);
75 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
77 SilcBufferParamType fmt;
79 SilcBool advance = FALSE;
81 /* Parse the arguments by formatting type. */
83 fmt = va_arg(ap, SilcBufferParamType);
88 SilcBufferFormatFunc func;
89 SilcBufferSFormatFunc funcs;
94 func = va_arg(ap, SilcBufferFormatFunc);
96 funcs = va_arg(ap, SilcBufferSFormatFunc);
97 val = va_arg(ap, void *);
98 context = va_arg(ap, void *);
100 tmp_len = func(dst, val, context);
102 tmp_len = funcs(stack, dst, val, context);
106 silc_buffer_pull(dst, tmp_len);
111 case SILC_PARAM_UI8_STRING:
112 case SILC_PARAM_UI16_STRING:
113 case SILC_PARAM_UI32_STRING:
114 case SILC_PARAM_UI8_STRING_ALLOC:
115 case SILC_PARAM_UI16_STRING_ALLOC:
116 case SILC_PARAM_UI32_STRING_ALLOC:
118 unsigned char *x = va_arg(ap, unsigned char *);
119 SilcUInt32 tmp_len = strlen(x);
120 FORMAT_HAS_SPACE(stack, dst, tmp_len);
121 silc_buffer_put(dst, x, tmp_len);
122 silc_buffer_pull(dst, tmp_len);
125 case SILC_PARAM_UI8_NSTRING:
126 case SILC_PARAM_UI16_NSTRING:
127 case SILC_PARAM_UI32_NSTRING:
128 case SILC_PARAM_UI_XNSTRING:
129 case SILC_PARAM_DATA:
130 case SILC_PARAM_UI8_NSTRING_ALLOC:
131 case SILC_PARAM_UI16_NSTRING_ALLOC:
132 case SILC_PARAM_UI32_NSTRING_ALLOC:
133 case SILC_PARAM_UI_XNSTRING_ALLOC:
134 case SILC_PARAM_DATA_ALLOC:
136 unsigned char *x = va_arg(ap, unsigned char *);
137 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
139 FORMAT_HAS_SPACE(stack, dst, tmp_len);
140 silc_buffer_put(dst, x, tmp_len);
141 silc_buffer_pull(dst, tmp_len);
145 case SILC_PARAM_UI8_CHAR:
147 unsigned char x = (unsigned char)va_arg(ap, int);
148 FORMAT_HAS_SPACE(stack, dst, 1);
149 silc_buffer_put(dst, &x, 1);
150 silc_buffer_pull(dst, 1);
153 case SILC_PARAM_UI16_SHORT:
156 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
157 FORMAT_HAS_SPACE(stack, dst, 2);
158 SILC_PUT16_MSB(x, xf);
159 silc_buffer_put(dst, xf, 2);
160 silc_buffer_pull(dst, 2);
163 case SILC_PARAM_UI32_INT:
166 SilcUInt32 x = va_arg(ap, SilcUInt32);
167 FORMAT_HAS_SPACE(stack, dst, 4);
168 SILC_PUT32_MSB(x, xf);
169 silc_buffer_put(dst, xf, 4);
170 silc_buffer_pull(dst, 4);
173 case SILC_PARAM_UI64_INT:
176 SilcUInt64 x = va_arg(ap, SilcUInt64);
177 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
178 SILC_PUT64_MSB(x, xf);
179 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
180 silc_buffer_pull(dst, sizeof(SilcUInt64));
183 case SILC_PARAM_SI8_CHAR:
185 char x = (char)va_arg(ap, int);
186 FORMAT_HAS_SPACE(stack, dst, 1);
187 silc_buffer_put(dst, &x, 1);
188 silc_buffer_pull(dst, 1);
191 case SILC_PARAM_SI16_SHORT:
194 SilcInt16 x = (SilcInt16)va_arg(ap, int);
195 FORMAT_HAS_SPACE(stack, dst, 2);
196 SILC_PUT16_MSB(x, xf);
197 silc_buffer_put(dst, xf, 2);
198 silc_buffer_pull(dst, 2);
201 case SILC_PARAM_SI32_INT:
204 SilcInt32 x = va_arg(ap, SilcInt32);
205 FORMAT_HAS_SPACE(stack, dst, 4);
206 SILC_PUT32_MSB(x, xf);
207 silc_buffer_put(dst, xf, 4);
208 silc_buffer_pull(dst, 4);
211 case SILC_PARAM_SI64_INT:
214 SilcInt64 x = va_arg(ap, SilcInt64);
215 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
216 SILC_PUT64_MSB(x, xf);
217 silc_buffer_put(dst, xf, sizeof(SilcInt64));
218 silc_buffer_pull(dst, sizeof(SilcInt64));
221 case SILC_PARAM_BUFFER:
222 case SILC_PARAM_BUFFER_ALLOC:
224 SilcBuffer x = va_arg(ap, SilcBuffer);
226 if (x && silc_buffer_len(x)) {
227 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
228 SILC_PUT32_MSB(silc_buffer_len(x), xf);
229 silc_buffer_put(dst, xf, 4);
230 silc_buffer_pull(dst, 4);
231 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
232 silc_buffer_pull(dst, silc_buffer_len(x));
236 case SILC_PARAM_OFFSET:
238 int offst = va_arg(ap, int);
242 if (offst > silc_buffer_len(dst))
244 silc_buffer_pull(dst, offst);
247 silc_buffer_push(dst, -(offst));
252 case SILC_PARAM_ADVANCE:
259 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
260 "format the data.", fmt));
267 SILC_LOG_DEBUG(("Error occured while formatting data"));
269 silc_buffer_push(dst, flen);
273 /* Push the buffer back to where it belongs. */
275 silc_buffer_push(dst, flen);
280 /****************************** Unformatting ********************************/
282 int silc_buffer_unformat(SilcBuffer src, ...)
288 ret = silc_buffer_sunformat_vp(NULL, src, ap);
294 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
296 return silc_buffer_sunformat_vp(NULL, src, ap);
299 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
305 ret = silc_buffer_sunformat_vp(stack, src, ap);
311 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
313 SilcBufferParamType fmt;
314 unsigned char *start_ptr = src->data;
317 /* Parse the arguments by formatting type. */
319 fmt = va_arg(ap, SilcBufferParamType);
322 case SILC_PARAM_FUNC:
324 SilcBufferUnformatFunc func;
325 SilcBufferSUnformatFunc funcs;
330 func = va_arg(ap, SilcBufferUnformatFunc);
332 funcs = va_arg(ap, SilcBufferSUnformatFunc);
333 val = va_arg(ap, void **);
334 context = va_arg(ap, void *);
336 tmp_len = func(src, val, context);
338 tmp_len = funcs(stack, src, val, context);
342 UNFORMAT_HAS_SPACE(src, tmp_len);
343 silc_buffer_pull(src, tmp_len);
346 case SILC_PARAM_UI_XNSTRING:
347 case SILC_PARAM_DATA:
349 unsigned char **x = va_arg(ap, unsigned char **);
350 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
351 UNFORMAT_HAS_SPACE(src, len2);
354 silc_buffer_pull(src, len2);
357 case SILC_PARAM_UI_XNSTRING_ALLOC:
358 case SILC_PARAM_DATA_ALLOC:
360 unsigned char **x = va_arg(ap, unsigned char **);
361 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
362 UNFORMAT_HAS_SPACE(src, len2);
364 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
365 memcpy(*x, src->data, len2);
367 silc_buffer_pull(src, len2);
370 case SILC_PARAM_UI8_CHAR:
372 unsigned char *x = va_arg(ap, unsigned char *);
373 UNFORMAT_HAS_SPACE(src, 1);
376 silc_buffer_pull(src, 1);
379 case SILC_PARAM_UI16_SHORT:
381 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
382 UNFORMAT_HAS_SPACE(src, 2);
384 SILC_GET16_MSB(*x, src->data);
385 silc_buffer_pull(src, 2);
388 case SILC_PARAM_UI32_INT:
390 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
391 UNFORMAT_HAS_SPACE(src, 4);
393 SILC_GET32_MSB(*x, src->data);
394 silc_buffer_pull(src, 4);
397 case SILC_PARAM_UI64_INT:
399 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
400 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
402 SILC_GET64_MSB(*x, src->data);
403 silc_buffer_pull(src, sizeof(SilcUInt64));
406 case SILC_PARAM_SI8_CHAR:
408 char *x = va_arg(ap, char *);
409 UNFORMAT_HAS_SPACE(src, 1);
412 silc_buffer_pull(src, 1);
415 case SILC_PARAM_SI16_SHORT:
417 SilcInt16 *x = va_arg(ap, SilcInt16 *);
418 UNFORMAT_HAS_SPACE(src, 2);
420 SILC_GET16_MSB(*x, src->data);
421 silc_buffer_pull(src, 2);
424 case SILC_PARAM_SI32_INT:
426 SilcInt32 *x = va_arg(ap, SilcInt32 *);
427 UNFORMAT_HAS_SPACE(src, 4);
429 SILC_GET32_MSB(*x, src->data);
430 silc_buffer_pull(src, 4);
433 case SILC_PARAM_SI64_INT:
435 SilcInt64 *x = va_arg(ap, SilcInt64 *);
436 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
438 SILC_GET64_MSB(*x, src->data);
439 silc_buffer_pull(src, sizeof(SilcInt64));
442 case SILC_PARAM_UI8_STRING:
445 unsigned char **x = va_arg(ap, unsigned char **);
446 UNFORMAT_HAS_SPACE(src, 1);
447 len2 = (SilcUInt8)src->data[0];
448 silc_buffer_pull(src, 1);
449 UNFORMAT_HAS_SPACE(src, len2);
452 silc_buffer_pull(src, len2);
455 case SILC_PARAM_UI16_STRING:
458 unsigned char **x = va_arg(ap, unsigned char **);
459 UNFORMAT_HAS_SPACE(src, 2);
460 SILC_GET16_MSB(len2, src->data);
461 silc_buffer_pull(src, 2);
462 UNFORMAT_HAS_SPACE(src, len2);
465 silc_buffer_pull(src, len2);
468 case SILC_PARAM_UI8_STRING_ALLOC:
471 unsigned char **x = va_arg(ap, unsigned char **);
472 UNFORMAT_HAS_SPACE(src, 1);
473 len2 = (SilcUInt8)src->data[0];
474 silc_buffer_pull(src, 1);
475 UNFORMAT_HAS_SPACE(src, len2);
477 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
478 memcpy(*x, src->data, len2);
480 silc_buffer_pull(src, len2);
483 case SILC_PARAM_UI16_STRING_ALLOC:
486 unsigned char **x = va_arg(ap, unsigned char **);
487 UNFORMAT_HAS_SPACE(src, 2);
488 SILC_GET16_MSB(len2, src->data);
489 silc_buffer_pull(src, 2);
490 UNFORMAT_HAS_SPACE(src, len2);
492 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
493 memcpy(*x, src->data, len2);
495 silc_buffer_pull(src, len2);
498 case SILC_PARAM_UI32_STRING:
501 unsigned char **x = va_arg(ap, unsigned char **);
502 UNFORMAT_HAS_SPACE(src, 4);
503 SILC_GET32_MSB(len2, src->data);
504 silc_buffer_pull(src, 4);
505 UNFORMAT_HAS_SPACE(src, len2);
508 silc_buffer_pull(src, len2);
511 case SILC_PARAM_UI32_STRING_ALLOC:
514 unsigned char **x = va_arg(ap, unsigned char **);
515 UNFORMAT_HAS_SPACE(src, 4);
516 SILC_GET32_MSB(len2, src->data);
517 silc_buffer_pull(src, 4);
518 UNFORMAT_HAS_SPACE(src, len2);
520 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
521 memcpy(*x, src->data, len2);
523 silc_buffer_pull(src, len2);
526 case SILC_PARAM_UI8_NSTRING:
529 unsigned char **x = va_arg(ap, unsigned char **);
530 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
531 UNFORMAT_HAS_SPACE(src, 1);
532 len2 = (SilcUInt8)src->data[0];
533 silc_buffer_pull(src, 1);
534 UNFORMAT_HAS_SPACE(src, len2);
539 silc_buffer_pull(src, len2);
542 case SILC_PARAM_UI16_NSTRING:
545 unsigned char **x = va_arg(ap, unsigned char **);
546 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
547 UNFORMAT_HAS_SPACE(src, 2);
548 SILC_GET16_MSB(len2, src->data);
549 silc_buffer_pull(src, 2);
550 UNFORMAT_HAS_SPACE(src, len2);
555 silc_buffer_pull(src, len2);
558 case SILC_PARAM_UI8_NSTRING_ALLOC:
561 unsigned char **x = va_arg(ap, unsigned char **);
562 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
563 UNFORMAT_HAS_SPACE(src, 1);
564 len2 = (SilcUInt8)src->data[0];
565 silc_buffer_pull(src, 1);
566 UNFORMAT_HAS_SPACE(src, len2);
570 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
571 memcpy(*x, src->data, len2);
573 silc_buffer_pull(src, len2);
576 case SILC_PARAM_UI16_NSTRING_ALLOC:
579 unsigned char **x = va_arg(ap, unsigned char **);
580 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
581 UNFORMAT_HAS_SPACE(src, 2);
582 SILC_GET16_MSB(len2, src->data);
583 silc_buffer_pull(src, 2);
584 UNFORMAT_HAS_SPACE(src, len2);
588 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
589 memcpy(*x, src->data, len2);
591 silc_buffer_pull(src, len2);
594 case SILC_PARAM_UI32_NSTRING:
597 unsigned char **x = va_arg(ap, unsigned char **);
598 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
599 UNFORMAT_HAS_SPACE(src, 4);
600 SILC_GET32_MSB(len2, src->data);
601 silc_buffer_pull(src, 4);
602 UNFORMAT_HAS_SPACE(src, len2);
607 silc_buffer_pull(src, len2);
610 case SILC_PARAM_BUFFER:
612 SilcBuffer x = va_arg(ap, SilcBuffer);
614 UNFORMAT_HAS_SPACE(src, 4);
615 SILC_GET32_MSB(len2, src->data);
616 silc_buffer_pull(src, 4);
617 UNFORMAT_HAS_SPACE(src, len2);
618 silc_buffer_set(x, src->data, len2);
619 silc_buffer_pull(src, len2);
622 case SILC_PARAM_BUFFER_ALLOC:
624 SilcBuffer x = va_arg(ap, SilcBuffer);
626 UNFORMAT_HAS_SPACE(src, 4);
627 SILC_GET32_MSB(len2, src->data);
628 silc_buffer_pull(src, 4);
629 UNFORMAT_HAS_SPACE(src, len2);
630 silc_buffer_sformat(stack, x,
631 SILC_STR_DATA(src->data, len2),
633 silc_buffer_pull(src, len2);
636 case SILC_PARAM_OFFSET:
638 int offst = va_arg(ap, int);
642 UNFORMAT_HAS_SPACE(src, offst);
643 silc_buffer_pull(src, offst);
645 silc_buffer_push(src, -(offst));
649 case SILC_PARAM_ADVANCE:
655 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
656 "format the data.", fmt));
663 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
664 len = src->data - start_ptr;
665 silc_buffer_push(src, len);
669 /* Push the buffer back to the start. */
670 len = src->data - start_ptr;
671 silc_buffer_push(src, len);
676 /**************************** Utility functions *****************************/
678 /* Formats strings into a buffer */
680 int silc_buffer_strformat(SilcBuffer dst, ...)
682 int len = silc_buffer_truelen(dst);
683 int hlen = silc_buffer_headlen(dst);
688 /* Parse the arguments by formatting type. */
690 char *string = va_arg(va, char *);
696 if (string == (char *)SILC_PARAM_END)
699 slen = strlen(string);
700 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
704 memcpy(dst->head + len, string, slen);
706 dst->head[len] = '\0';
709 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
714 dst->end = dst->head + len;
715 dst->data = dst->head + hlen;
716 dst->tail = dst->end;
722 /* Formats strings into a buffer. Allocates memory from SilcStack. */
724 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
726 int len = silc_buffer_truelen(dst);
727 int hlen = silc_buffer_headlen(dst);
732 /* Parse the arguments by formatting type. */
734 char *string = va_arg(va, char *);
740 if (string == (char *)SILC_PARAM_END)
743 slen = strlen(string);
744 d = silc_srealloc_ua(stack, len + 1, dst->head,
745 sizeof(*dst->head) * (slen + len + 1));
749 memcpy(dst->head + len, string, slen);
751 dst->head[len] = '\0';
754 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
759 dst->end = dst->head + len;
760 dst->data = dst->head + hlen;
761 dst->tail = dst->end;