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_unlikely(!silc_buffer_senlarge(s, b, req))) \
34 /* Check that there is data to be unformatted */
35 #define UNFORMAT_HAS_SPACE(b, req) \
37 if (silc_unlikely(req > silc_buffer_len(b))) \
39 if (silc_unlikely((req + 1) <= 0)) \
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 = NULL;
89 SilcBufferSFormatFunc funcs = NULL;
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;
316 SilcBool advance = FALSE;
318 /* Parse the arguments by formatting type. */
320 fmt = va_arg(ap, SilcBufferParamType);
323 case SILC_PARAM_FUNC:
325 SilcBufferUnformatFunc func = NULL;
326 SilcBufferSUnformatFunc funcs = NULL;
331 func = va_arg(ap, SilcBufferUnformatFunc);
333 funcs = va_arg(ap, SilcBufferSUnformatFunc);
334 val = va_arg(ap, void **);
335 context = va_arg(ap, void *);
337 tmp_len = func(src, val, context);
339 tmp_len = funcs(stack, src, val, context);
343 UNFORMAT_HAS_SPACE(src, tmp_len);
344 silc_buffer_pull(src, tmp_len);
347 case SILC_PARAM_UI_XNSTRING:
348 case SILC_PARAM_DATA:
350 unsigned char **x = va_arg(ap, unsigned char **);
351 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
352 UNFORMAT_HAS_SPACE(src, len2);
353 if (silc_likely(len2 && x))
355 silc_buffer_pull(src, len2);
358 case SILC_PARAM_UI_XNSTRING_ALLOC:
359 case SILC_PARAM_DATA_ALLOC:
361 unsigned char **x = va_arg(ap, unsigned char **);
362 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
363 UNFORMAT_HAS_SPACE(src, len2);
364 if (silc_likely(len2 && x)) {
365 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
366 memcpy(*x, src->data, len2);
368 silc_buffer_pull(src, len2);
371 case SILC_PARAM_UI8_CHAR:
373 unsigned char *x = va_arg(ap, unsigned char *);
374 UNFORMAT_HAS_SPACE(src, 1);
377 silc_buffer_pull(src, 1);
380 case SILC_PARAM_UI16_SHORT:
382 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
383 UNFORMAT_HAS_SPACE(src, 2);
385 SILC_GET16_MSB(*x, src->data);
386 silc_buffer_pull(src, 2);
389 case SILC_PARAM_UI32_INT:
391 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
392 UNFORMAT_HAS_SPACE(src, 4);
394 SILC_GET32_MSB(*x, src->data);
395 silc_buffer_pull(src, 4);
398 case SILC_PARAM_UI64_INT:
400 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
401 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
403 SILC_GET64_MSB(*x, src->data);
404 silc_buffer_pull(src, sizeof(SilcUInt64));
407 case SILC_PARAM_SI8_CHAR:
409 char *x = va_arg(ap, char *);
410 UNFORMAT_HAS_SPACE(src, 1);
413 silc_buffer_pull(src, 1);
416 case SILC_PARAM_SI16_SHORT:
418 SilcInt16 *x = va_arg(ap, SilcInt16 *);
419 UNFORMAT_HAS_SPACE(src, 2);
421 SILC_GET16_MSB(*x, src->data);
422 silc_buffer_pull(src, 2);
425 case SILC_PARAM_SI32_INT:
427 SilcInt32 *x = va_arg(ap, SilcInt32 *);
428 UNFORMAT_HAS_SPACE(src, 4);
430 SILC_GET32_MSB(*x, src->data);
431 silc_buffer_pull(src, 4);
434 case SILC_PARAM_SI64_INT:
436 SilcInt64 *x = va_arg(ap, SilcInt64 *);
437 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
439 SILC_GET64_MSB(*x, src->data);
440 silc_buffer_pull(src, sizeof(SilcInt64));
443 case SILC_PARAM_UI8_STRING:
446 unsigned char **x = va_arg(ap, unsigned char **);
447 UNFORMAT_HAS_SPACE(src, 1);
448 len2 = (SilcUInt8)src->data[0];
449 silc_buffer_pull(src, 1);
450 UNFORMAT_HAS_SPACE(src, len2);
453 silc_buffer_pull(src, len2);
456 case SILC_PARAM_UI16_STRING:
459 unsigned char **x = va_arg(ap, unsigned char **);
460 UNFORMAT_HAS_SPACE(src, 2);
461 SILC_GET16_MSB(len2, src->data);
462 silc_buffer_pull(src, 2);
463 UNFORMAT_HAS_SPACE(src, len2);
466 silc_buffer_pull(src, len2);
469 case SILC_PARAM_UI8_STRING_ALLOC:
472 unsigned char **x = va_arg(ap, unsigned char **);
473 UNFORMAT_HAS_SPACE(src, 1);
474 len2 = (SilcUInt8)src->data[0];
475 silc_buffer_pull(src, 1);
476 UNFORMAT_HAS_SPACE(src, len2);
477 if (silc_likely(x && len2)) {
478 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
479 memcpy(*x, src->data, len2);
481 silc_buffer_pull(src, len2);
484 case SILC_PARAM_UI16_STRING_ALLOC:
487 unsigned char **x = va_arg(ap, unsigned char **);
488 UNFORMAT_HAS_SPACE(src, 2);
489 SILC_GET16_MSB(len2, src->data);
490 silc_buffer_pull(src, 2);
491 UNFORMAT_HAS_SPACE(src, len2);
492 if (silc_likely(x && len2)) {
493 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
494 memcpy(*x, src->data, len2);
496 silc_buffer_pull(src, len2);
499 case SILC_PARAM_UI32_STRING:
502 unsigned char **x = va_arg(ap, unsigned char **);
503 UNFORMAT_HAS_SPACE(src, 4);
504 SILC_GET32_MSB(len2, src->data);
505 silc_buffer_pull(src, 4);
506 UNFORMAT_HAS_SPACE(src, len2);
509 silc_buffer_pull(src, len2);
512 case SILC_PARAM_UI32_STRING_ALLOC:
515 unsigned char **x = va_arg(ap, unsigned char **);
516 UNFORMAT_HAS_SPACE(src, 4);
517 SILC_GET32_MSB(len2, src->data);
518 silc_buffer_pull(src, 4);
519 UNFORMAT_HAS_SPACE(src, len2);
520 if (silc_likely(x && len2)) {
521 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
522 memcpy(*x, src->data, len2);
524 silc_buffer_pull(src, len2);
527 case SILC_PARAM_UI8_NSTRING:
530 unsigned char **x = va_arg(ap, unsigned char **);
531 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
532 UNFORMAT_HAS_SPACE(src, 1);
533 len2 = (SilcUInt8)src->data[0];
534 silc_buffer_pull(src, 1);
535 UNFORMAT_HAS_SPACE(src, len2);
540 silc_buffer_pull(src, len2);
543 case SILC_PARAM_UI16_NSTRING:
546 unsigned char **x = va_arg(ap, unsigned char **);
547 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
548 UNFORMAT_HAS_SPACE(src, 2);
549 SILC_GET16_MSB(len2, src->data);
550 silc_buffer_pull(src, 2);
551 UNFORMAT_HAS_SPACE(src, len2);
556 silc_buffer_pull(src, len2);
559 case SILC_PARAM_UI8_NSTRING_ALLOC:
562 unsigned char **x = va_arg(ap, unsigned char **);
563 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
564 UNFORMAT_HAS_SPACE(src, 1);
565 len2 = (SilcUInt8)src->data[0];
566 silc_buffer_pull(src, 1);
567 UNFORMAT_HAS_SPACE(src, len2);
571 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
572 memcpy(*x, src->data, len2);
574 silc_buffer_pull(src, len2);
577 case SILC_PARAM_UI16_NSTRING_ALLOC:
580 unsigned char **x = va_arg(ap, unsigned char **);
581 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
582 UNFORMAT_HAS_SPACE(src, 2);
583 SILC_GET16_MSB(len2, src->data);
584 silc_buffer_pull(src, 2);
585 UNFORMAT_HAS_SPACE(src, len2);
589 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
590 memcpy(*x, src->data, len2);
592 silc_buffer_pull(src, len2);
595 case SILC_PARAM_UI32_NSTRING:
598 unsigned char **x = va_arg(ap, unsigned char **);
599 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
600 UNFORMAT_HAS_SPACE(src, 4);
601 SILC_GET32_MSB(len2, src->data);
602 silc_buffer_pull(src, 4);
603 UNFORMAT_HAS_SPACE(src, len2);
608 silc_buffer_pull(src, len2);
611 case SILC_PARAM_BUFFER:
613 SilcBuffer x = va_arg(ap, SilcBuffer);
615 UNFORMAT_HAS_SPACE(src, 4);
616 SILC_GET32_MSB(len2, src->data);
617 silc_buffer_pull(src, 4);
618 UNFORMAT_HAS_SPACE(src, len2);
619 silc_buffer_set(x, src->data, len2);
620 silc_buffer_pull(src, len2);
623 case SILC_PARAM_BUFFER_ALLOC:
625 SilcBuffer x = va_arg(ap, SilcBuffer);
627 UNFORMAT_HAS_SPACE(src, 4);
628 SILC_GET32_MSB(len2, src->data);
629 silc_buffer_pull(src, 4);
630 UNFORMAT_HAS_SPACE(src, len2);
631 silc_buffer_sformat(stack, x,
632 SILC_STR_DATA(src->data, len2),
634 silc_buffer_pull(src, len2);
637 case SILC_PARAM_OFFSET:
639 int offst = va_arg(ap, int);
643 UNFORMAT_HAS_SPACE(src, offst);
644 silc_buffer_pull(src, offst);
646 silc_buffer_push(src, -(offst));
650 case SILC_PARAM_ADVANCE:
657 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
658 "format the data.", fmt));
665 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
666 len = src->data - start_ptr;
667 silc_buffer_push(src, len);
671 /* Push the buffer back to the start. */
673 len = src->data - start_ptr;
674 silc_buffer_push(src, len);
680 /**************************** Utility functions *****************************/
682 /* Formats strings into a buffer */
684 int silc_buffer_strformat(SilcBuffer dst, ...)
686 int len = silc_buffer_truelen(dst);
687 int hlen = silc_buffer_headlen(dst);
692 /* Parse the arguments by formatting type. */
694 char *string = va_arg(va, char *);
700 if (string == (char *)SILC_PARAM_END)
703 slen = strlen(string);
704 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
705 if (silc_unlikely(!d))
708 memcpy(dst->head + len, string, slen);
710 dst->head[len] = '\0';
713 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
718 dst->end = dst->head + len;
719 dst->data = dst->head + hlen;
720 dst->tail = dst->end;
726 /* Formats strings into a buffer. Allocates memory from SilcStack. */
728 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
730 int len = silc_buffer_truelen(dst);
731 int hlen = silc_buffer_headlen(dst);
736 /* Parse the arguments by formatting type. */
738 char *string = va_arg(va, char *);
744 if (string == (char *)SILC_PARAM_END)
747 slen = strlen(string);
748 d = silc_srealloc_ua(stack, len + 1, dst->head,
749 sizeof(*dst->head) * (slen + len + 1));
750 if (silc_unlikely(!d))
753 memcpy(dst->head + len, string, slen);
755 dst->head[len] = '\0';
758 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
763 dst->end = dst->head + len;
764 dst->data = dst->head + hlen;
765 dst->tail = dst->end;