5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 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 = x ? strlen(x) : 0;
121 FORMAT_HAS_SPACE(stack, dst, tmp_len);
122 silc_buffer_put(dst, x, tmp_len);
123 silc_buffer_pull(dst, tmp_len);
127 case SILC_PARAM_UI8_NSTRING:
128 case SILC_PARAM_UI16_NSTRING:
129 case SILC_PARAM_UI32_NSTRING:
130 case SILC_PARAM_UI_XNSTRING:
131 case SILC_PARAM_DATA:
132 case SILC_PARAM_UI8_NSTRING_ALLOC:
133 case SILC_PARAM_UI16_NSTRING_ALLOC:
134 case SILC_PARAM_UI32_NSTRING_ALLOC:
135 case SILC_PARAM_UI_XNSTRING_ALLOC:
136 case SILC_PARAM_DATA_ALLOC:
138 unsigned char *x = va_arg(ap, unsigned char *);
139 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
141 FORMAT_HAS_SPACE(stack, dst, tmp_len);
142 silc_buffer_put(dst, x, tmp_len);
143 silc_buffer_pull(dst, tmp_len);
147 case SILC_PARAM_UI8_CHAR:
149 unsigned char x = (unsigned char)va_arg(ap, int);
150 FORMAT_HAS_SPACE(stack, dst, 1);
151 silc_buffer_put(dst, &x, 1);
152 silc_buffer_pull(dst, 1);
155 case SILC_PARAM_UI16_SHORT:
158 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
159 FORMAT_HAS_SPACE(stack, dst, 2);
160 SILC_PUT16_MSB(x, xf);
161 silc_buffer_put(dst, xf, 2);
162 silc_buffer_pull(dst, 2);
165 case SILC_PARAM_UI32_INT:
168 SilcUInt32 x = va_arg(ap, SilcUInt32);
169 FORMAT_HAS_SPACE(stack, dst, 4);
170 SILC_PUT32_MSB(x, xf);
171 silc_buffer_put(dst, xf, 4);
172 silc_buffer_pull(dst, 4);
175 case SILC_PARAM_UI64_INT:
178 SilcUInt64 x = va_arg(ap, SilcUInt64);
179 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
180 SILC_PUT64_MSB(x, xf);
181 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
182 silc_buffer_pull(dst, sizeof(SilcUInt64));
185 case SILC_PARAM_SI8_CHAR:
187 char x = (char)va_arg(ap, int);
188 FORMAT_HAS_SPACE(stack, dst, 1);
189 silc_buffer_put(dst, &x, 1);
190 silc_buffer_pull(dst, 1);
193 case SILC_PARAM_SI16_SHORT:
196 SilcInt16 x = (SilcInt16)va_arg(ap, int);
197 FORMAT_HAS_SPACE(stack, dst, 2);
198 SILC_PUT16_MSB(x, xf);
199 silc_buffer_put(dst, xf, 2);
200 silc_buffer_pull(dst, 2);
203 case SILC_PARAM_SI32_INT:
206 SilcInt32 x = va_arg(ap, SilcInt32);
207 FORMAT_HAS_SPACE(stack, dst, 4);
208 SILC_PUT32_MSB(x, xf);
209 silc_buffer_put(dst, xf, 4);
210 silc_buffer_pull(dst, 4);
213 case SILC_PARAM_SI64_INT:
216 SilcInt64 x = va_arg(ap, SilcInt64);
217 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
218 SILC_PUT64_MSB(x, xf);
219 silc_buffer_put(dst, xf, sizeof(SilcInt64));
220 silc_buffer_pull(dst, sizeof(SilcInt64));
223 case SILC_PARAM_BUFFER:
224 case SILC_PARAM_BUFFER_ALLOC:
226 SilcBuffer x = va_arg(ap, SilcBuffer);
228 if (x && silc_buffer_len(x)) {
229 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
230 SILC_PUT32_MSB(silc_buffer_len(x), xf);
231 silc_buffer_put(dst, xf, 4);
232 silc_buffer_pull(dst, 4);
233 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
234 silc_buffer_pull(dst, silc_buffer_len(x));
238 case SILC_PARAM_OFFSET:
240 int offst = va_arg(ap, int);
244 if (offst > silc_buffer_len(dst))
246 silc_buffer_pull(dst, offst);
249 silc_buffer_push(dst, -(offst));
254 case SILC_PARAM_ADVANCE:
261 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
262 "format the data.", fmt));
269 SILC_LOG_DEBUG(("Error occured while formatting data"));
271 silc_buffer_push(dst, flen);
275 /* Push the buffer back to where it belongs. */
277 silc_buffer_push(dst, flen);
282 /****************************** Unformatting ********************************/
284 int silc_buffer_unformat(SilcBuffer src, ...)
290 ret = silc_buffer_sunformat_vp(NULL, src, ap);
296 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
298 return silc_buffer_sunformat_vp(NULL, src, ap);
301 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
307 ret = silc_buffer_sunformat_vp(stack, src, ap);
313 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
315 SilcBufferParamType fmt;
316 unsigned char *start_ptr = src->data;
318 SilcBool advance = FALSE;
320 /* Parse the arguments by formatting type. */
322 fmt = va_arg(ap, SilcBufferParamType);
325 case SILC_PARAM_FUNC:
327 SilcBufferUnformatFunc func = NULL;
328 SilcBufferSUnformatFunc funcs = NULL;
333 func = va_arg(ap, SilcBufferUnformatFunc);
335 funcs = va_arg(ap, SilcBufferSUnformatFunc);
336 val = va_arg(ap, void **);
337 context = va_arg(ap, void *);
339 tmp_len = func(src, val, context);
341 tmp_len = funcs(stack, src, val, context);
345 UNFORMAT_HAS_SPACE(src, tmp_len);
346 silc_buffer_pull(src, tmp_len);
349 case SILC_PARAM_UI_XNSTRING:
350 case SILC_PARAM_DATA:
352 unsigned char **x = va_arg(ap, unsigned char **);
353 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
354 UNFORMAT_HAS_SPACE(src, len2);
355 if (silc_likely(len2 && x))
357 silc_buffer_pull(src, len2);
360 case SILC_PARAM_UI_XNSTRING_ALLOC:
361 case SILC_PARAM_DATA_ALLOC:
363 unsigned char **x = va_arg(ap, unsigned char **);
364 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
365 UNFORMAT_HAS_SPACE(src, len2);
366 if (silc_likely(len2 && x)) {
367 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
368 memcpy(*x, src->data, len2);
370 silc_buffer_pull(src, len2);
373 case SILC_PARAM_UI8_CHAR:
375 unsigned char *x = va_arg(ap, unsigned char *);
376 UNFORMAT_HAS_SPACE(src, 1);
379 silc_buffer_pull(src, 1);
382 case SILC_PARAM_UI16_SHORT:
384 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
385 UNFORMAT_HAS_SPACE(src, 2);
387 SILC_GET16_MSB(*x, src->data);
388 silc_buffer_pull(src, 2);
391 case SILC_PARAM_UI32_INT:
393 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
394 UNFORMAT_HAS_SPACE(src, 4);
396 SILC_GET32_MSB(*x, src->data);
397 silc_buffer_pull(src, 4);
400 case SILC_PARAM_UI64_INT:
402 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
403 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
405 SILC_GET64_MSB(*x, src->data);
406 silc_buffer_pull(src, sizeof(SilcUInt64));
409 case SILC_PARAM_SI8_CHAR:
411 char *x = va_arg(ap, char *);
412 UNFORMAT_HAS_SPACE(src, 1);
415 silc_buffer_pull(src, 1);
418 case SILC_PARAM_SI16_SHORT:
420 SilcInt16 *x = va_arg(ap, SilcInt16 *);
421 UNFORMAT_HAS_SPACE(src, 2);
423 SILC_GET16_MSB(*x, src->data);
424 silc_buffer_pull(src, 2);
427 case SILC_PARAM_SI32_INT:
429 SilcInt32 *x = va_arg(ap, SilcInt32 *);
430 UNFORMAT_HAS_SPACE(src, 4);
432 SILC_GET32_MSB(*x, src->data);
433 silc_buffer_pull(src, 4);
436 case SILC_PARAM_SI64_INT:
438 SilcInt64 *x = va_arg(ap, SilcInt64 *);
439 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
441 SILC_GET64_MSB(*x, src->data);
442 silc_buffer_pull(src, sizeof(SilcInt64));
445 case SILC_PARAM_UI8_STRING:
448 unsigned char **x = va_arg(ap, unsigned char **);
449 UNFORMAT_HAS_SPACE(src, 1);
450 len2 = (SilcUInt8)src->data[0];
451 silc_buffer_pull(src, 1);
452 UNFORMAT_HAS_SPACE(src, len2);
455 silc_buffer_pull(src, len2);
458 case SILC_PARAM_UI16_STRING:
461 unsigned char **x = va_arg(ap, unsigned char **);
462 UNFORMAT_HAS_SPACE(src, 2);
463 SILC_GET16_MSB(len2, src->data);
464 silc_buffer_pull(src, 2);
465 UNFORMAT_HAS_SPACE(src, len2);
468 silc_buffer_pull(src, len2);
471 case SILC_PARAM_UI8_STRING_ALLOC:
474 unsigned char **x = va_arg(ap, unsigned char **);
475 UNFORMAT_HAS_SPACE(src, 1);
476 len2 = (SilcUInt8)src->data[0];
477 silc_buffer_pull(src, 1);
478 UNFORMAT_HAS_SPACE(src, len2);
479 if (silc_likely(x && len2)) {
480 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
481 memcpy(*x, src->data, len2);
483 silc_buffer_pull(src, len2);
486 case SILC_PARAM_UI16_STRING_ALLOC:
489 unsigned char **x = va_arg(ap, unsigned char **);
490 UNFORMAT_HAS_SPACE(src, 2);
491 SILC_GET16_MSB(len2, src->data);
492 silc_buffer_pull(src, 2);
493 UNFORMAT_HAS_SPACE(src, len2);
494 if (silc_likely(x && len2)) {
495 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
496 memcpy(*x, src->data, len2);
498 silc_buffer_pull(src, len2);
501 case SILC_PARAM_UI32_STRING:
504 unsigned char **x = va_arg(ap, unsigned char **);
505 UNFORMAT_HAS_SPACE(src, 4);
506 SILC_GET32_MSB(len2, src->data);
507 silc_buffer_pull(src, 4);
508 UNFORMAT_HAS_SPACE(src, len2);
511 silc_buffer_pull(src, len2);
514 case SILC_PARAM_UI32_STRING_ALLOC:
517 unsigned char **x = va_arg(ap, unsigned char **);
518 UNFORMAT_HAS_SPACE(src, 4);
519 SILC_GET32_MSB(len2, src->data);
520 silc_buffer_pull(src, 4);
521 UNFORMAT_HAS_SPACE(src, len2);
522 if (silc_likely(x && len2)) {
523 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
524 memcpy(*x, src->data, len2);
526 silc_buffer_pull(src, len2);
529 case SILC_PARAM_UI8_NSTRING:
532 unsigned char **x = va_arg(ap, unsigned char **);
533 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
534 UNFORMAT_HAS_SPACE(src, 1);
535 len2 = (SilcUInt8)src->data[0];
536 silc_buffer_pull(src, 1);
537 UNFORMAT_HAS_SPACE(src, len2);
542 silc_buffer_pull(src, len2);
545 case SILC_PARAM_UI16_NSTRING:
548 unsigned char **x = va_arg(ap, unsigned char **);
549 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
550 UNFORMAT_HAS_SPACE(src, 2);
551 SILC_GET16_MSB(len2, src->data);
552 silc_buffer_pull(src, 2);
553 UNFORMAT_HAS_SPACE(src, len2);
558 silc_buffer_pull(src, len2);
561 case SILC_PARAM_UI8_NSTRING_ALLOC:
564 unsigned char **x = va_arg(ap, unsigned char **);
565 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
566 UNFORMAT_HAS_SPACE(src, 1);
567 len2 = (SilcUInt8)src->data[0];
568 silc_buffer_pull(src, 1);
569 UNFORMAT_HAS_SPACE(src, len2);
573 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
574 memcpy(*x, src->data, len2);
576 silc_buffer_pull(src, len2);
579 case SILC_PARAM_UI16_NSTRING_ALLOC:
582 unsigned char **x = va_arg(ap, unsigned char **);
583 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
584 UNFORMAT_HAS_SPACE(src, 2);
585 SILC_GET16_MSB(len2, src->data);
586 silc_buffer_pull(src, 2);
587 UNFORMAT_HAS_SPACE(src, len2);
591 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
592 memcpy(*x, src->data, len2);
594 silc_buffer_pull(src, len2);
597 case SILC_PARAM_UI32_NSTRING:
600 unsigned char **x = va_arg(ap, unsigned char **);
601 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
602 UNFORMAT_HAS_SPACE(src, 4);
603 SILC_GET32_MSB(len2, src->data);
604 silc_buffer_pull(src, 4);
605 UNFORMAT_HAS_SPACE(src, len2);
610 silc_buffer_pull(src, len2);
613 case SILC_PARAM_BUFFER:
615 SilcBuffer x = va_arg(ap, SilcBuffer);
617 UNFORMAT_HAS_SPACE(src, 4);
618 SILC_GET32_MSB(len2, src->data);
619 silc_buffer_pull(src, 4);
620 UNFORMAT_HAS_SPACE(src, len2);
621 silc_buffer_set(x, src->data, len2);
622 silc_buffer_pull(src, len2);
625 case SILC_PARAM_BUFFER_ALLOC:
627 SilcBuffer x = va_arg(ap, SilcBuffer);
629 UNFORMAT_HAS_SPACE(src, 4);
630 SILC_GET32_MSB(len2, src->data);
631 silc_buffer_pull(src, 4);
632 UNFORMAT_HAS_SPACE(src, len2);
633 silc_buffer_sformat(stack, x,
634 SILC_STR_DATA(src->data, len2),
636 silc_buffer_pull(src, len2);
639 case SILC_PARAM_OFFSET:
641 int offst = va_arg(ap, int);
645 UNFORMAT_HAS_SPACE(src, offst);
646 silc_buffer_pull(src, offst);
648 silc_buffer_push(src, -(offst));
652 case SILC_PARAM_ADVANCE:
659 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
660 "format the data.", fmt));
667 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
668 len = src->data - start_ptr;
669 silc_buffer_push(src, len);
673 /* Push the buffer back to the start. */
675 len = src->data - start_ptr;
676 silc_buffer_push(src, len);
682 /**************************** Utility functions *****************************/
684 /* Formats strings into a buffer */
686 int silc_buffer_strformat(SilcBuffer dst, ...)
688 int len = silc_buffer_truelen(dst);
689 int hlen = silc_buffer_headlen(dst);
694 /* Parse the arguments by formatting type. */
696 char *string = va_arg(va, char *);
702 if (string == (char *)SILC_PARAM_END)
705 slen = strlen(string);
706 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
707 if (silc_unlikely(!d))
710 memcpy(dst->head + len, string, slen);
712 dst->head[len] = '\0';
715 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
720 dst->end = dst->head + len;
721 dst->data = dst->head + hlen;
722 dst->tail = dst->end;
728 /* Formats strings into a buffer. Allocates memory from SilcStack. */
730 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
732 int len = silc_buffer_truelen(dst);
733 int hlen = silc_buffer_headlen(dst);
738 /* Parse the arguments by formatting type. */
740 char *string = va_arg(va, char *);
746 if (string == (char *)SILC_PARAM_END)
749 slen = strlen(string);
750 d = silc_srealloc(stack, len + 1, dst->head,
751 sizeof(*dst->head) * (slen + len + 1));
752 if (silc_unlikely(!d))
755 memcpy(dst->head + len, string, slen);
757 dst->head[len] = '\0';
760 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
765 dst->end = dst->head + len;
766 dst->data = dst->head + hlen;
767 dst->tail = dst->end;