5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2008 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 buffer has enough room to format data in it, if not
35 allocate more. This will append, thus not replacing any existing data. */
36 #define FORMAT_HAS_SPACE_APPEND(s, b, req) \
38 if (silc_buffer_len(b) < req) \
39 if (silc_unlikely(!silc_buffer_sappend(s, b, req - silc_buffer_len(b)))) \
44 /* Check that there is data to be unformatted */
45 #define UNFORMAT_HAS_SPACE(b, req) \
47 if (silc_unlikely(req > silc_buffer_len(b))) { \
48 silc_set_errno(SILC_ERR_OVERFLOW); \
51 if (silc_unlikely((req + 1) <= 0)) { \
52 silc_set_errno(SILC_ERR_UNDERFLOW); \
57 #if defined(SILC_DEBUG)
58 static const char *silc_param_string(SilcParam fmt)
60 if (fmt == SILC_PARAM_SINT8)
62 if (fmt == SILC_PARAM_UINT8)
64 if (fmt == SILC_PARAM_SINT16)
66 if (fmt == SILC_PARAM_UINT16)
68 if (fmt == SILC_PARAM_SINT32)
70 if (fmt == SILC_PARAM_UINT32)
72 if (fmt == SILC_PARAM_SINT64)
74 if (fmt == SILC_PARAM_UINT64)
76 if (fmt == SILC_PARAM_SICHAR)
78 if (fmt == (SILC_PARAM_SICHAR | SILC_PARAM_ALLOC))
79 return "SICHAR ALLOC";
80 if (fmt == SILC_PARAM_UICHAR)
82 if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_ALLOC))
83 return "UICHAR ALLOC";
84 if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_REPLACE))
85 return "UICHAR REPLACE";
86 if (fmt == SILC_PARAM_BUFFER)
88 if (fmt == (SILC_PARAM_BUFFER | SILC_PARAM_ALLOC))
89 return "BUFFER ALLOC";
90 if (fmt == SILC_PARAM_PTR)
92 if (fmt == SILC_PARAM_END)
94 if (fmt == SILC_PARAM_UI8_STRING)
96 if (fmt == SILC_PARAM_UI16_STRING)
98 if (fmt == SILC_PARAM_UI32_STRING)
100 if (fmt == SILC_PARAM_UI8_NSTRING)
102 if (fmt == SILC_PARAM_UI16_NSTRING)
103 return "UI16_STRING";
104 if (fmt == SILC_PARAM_UI32_NSTRING)
105 return "UI32_STRING";
106 if (fmt == (SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC))
107 return "UI8_STRING ALLOC";
108 if (fmt == (SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC))
109 return "UI16_STRING ALLOC";
110 if (fmt == (SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC))
111 return "UI32_STRING ALLOC";
112 if (fmt == (SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC))
113 return "UI8_STRING ALLOC";
114 if (fmt == (SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC))
115 return "UI16_STRING ALLOC";
116 if (fmt == (SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC))
117 return "UI32_STRING";
118 if (fmt == SILC_PARAM_OFFSET)
120 if (fmt == SILC_PARAM_ADVANCE)
122 if (fmt == SILC_PARAM_FUNC)
124 if (fmt == SILC_PARAM_REGEX)
126 if (fmt == SILC_PARAM_OFFSET_START)
127 return "OFFSET_START";
128 if (fmt == SILC_PARAM_OFFSET_END)
130 if (fmt == SILC_PARAM_DELETE)
134 #endif /* SILC_DEBUG */
136 /******************************* Formatting *********************************/
138 int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
143 SilcBool advance = FALSE;
145 /* Parse the arguments by formatting type. */
147 fmt = va_arg(ap, SilcParam);
149 #if defined(SILC_DEBUG)
151 SILC_LOG_DEBUG(("Buffer format type %s (%d)",
152 silc_param_string(fmt), fmt));
153 #endif /* SILC_DEBUG */
156 case SILC_PARAM_FUNC:
158 SilcBufferFormatFunc func;
163 func = va_arg(ap, SilcBufferFormatFunc);
164 val = va_arg(ap, void *);
165 context = va_arg(ap, void *);
170 tmp_len = func(stack, dst, val, context);
174 silc_buffer_pull(dst, tmp_len);
180 case SILC_PARAM_REGEX:
182 const char *regex = va_arg(ap, char *);
183 SilcBufferRegexFlags rflags = va_arg(ap, SilcUInt32);
184 SilcBufferStruct match;
185 SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
186 SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
188 SilcUInt32 inclusive_pos = 0;
189 int matched = 0, ret_len;
200 /* Match for '\n' in the buffer. If not found, treat as line
201 without '\n' (buffer has only one line, or this is last line). */
202 if (silc_regex_buffer(dst, "\n", &match, NULL))
203 dst->tail = match.tail;
208 ret = silc_regex_buffer(dst, regex, &match, NULL);
209 ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
211 if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
212 silc_set_errno(SILC_ERR_NOT_FOUND);
219 if (rflags & SILC_STR_REGEX_NOT)
222 if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
223 /* Advance buffer after match */
224 flen += (match.data - dst->data);
225 if (!silc_buffer_pull(dst, (match.data - dst->data)))
229 if (rflags & SILC_STR_REGEX_INCLUSIVE) {
230 inclusive_pos = dst->tail - match.tail;
231 dst->tail = match.tail;
234 /* Recursively format */
235 silc_va_copy(cp, ap);
236 ret_len = silc_buffer_sformat_vp_i(stack, dst, cp, TRUE);
241 if (rflags & SILC_STR_REGEX_INCLUSIVE)
242 if (!silc_buffer_pull_tail(dst, inclusive_pos))
245 /* Advance buffer after formatting */
247 if (!silc_buffer_pull(dst, ret_len))
250 if (match_all && (!match_nl || silc_buffer_len(dst) > 1))
255 /* Go to next line, it is at the end of the data area. Adjust
256 the tail area of the target buffer to show rest of the buffer. */
257 flen += (dst->tail - dst->data);
258 if (!silc_buffer_pull(dst, (dst->tail - dst->data)))
260 if (!silc_buffer_pull_tail(dst, silc_buffer_taillen(dst)))
263 if (silc_buffer_len(dst) > 0)
267 /* Skip to the next SILC_PARAM_END */
268 silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE);
272 case SILC_PARAM_UI8_STRING:
273 case SILC_PARAM_UI16_STRING:
274 case SILC_PARAM_UI32_STRING:
275 case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
276 case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
277 case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
279 char *x = va_arg(ap, char *);
280 SilcUInt32 tmp_len = x ? strlen(x) : 0;
286 FORMAT_HAS_SPACE(stack, dst, tmp_len);
287 silc_buffer_put(dst, x, tmp_len);
288 silc_buffer_pull(dst, tmp_len);
293 case SILC_PARAM_UICHAR | SILC_PARAM_REPLACE:
295 unsigned char *x = va_arg(ap, unsigned char *);
296 SilcUInt32 x_len = va_arg(ap, SilcUInt32);
304 if (silc_buffer_len(dst) == x_len) {
307 silc_buffer_put(dst, x, x_len);
308 silc_buffer_pull(dst, x_len);
311 } else if (silc_buffer_len(dst) < x_len) {
314 FORMAT_HAS_SPACE_APPEND(stack, dst, x_len);
315 silc_buffer_put(dst, x, x_len);
316 silc_buffer_pull(dst, x_len);
321 silc_buffer_put(dst, x, x_len);
322 silc_buffer_pull(dst, x_len);
330 case SILC_PARAM_UI8_NSTRING:
331 case SILC_PARAM_UI16_NSTRING:
332 case SILC_PARAM_UI32_NSTRING:
333 case SILC_PARAM_UICHAR:
334 case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
335 case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
336 case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
337 case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
339 unsigned char *x = va_arg(ap, unsigned char *);
340 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
346 FORMAT_HAS_SPACE(stack, dst, tmp_len);
347 silc_buffer_put(dst, x, tmp_len);
348 silc_buffer_pull(dst, tmp_len);
353 case SILC_PARAM_UINT8:
355 unsigned char x = (unsigned char)va_arg(ap, int);
360 FORMAT_HAS_SPACE(stack, dst, 1);
361 silc_buffer_put(dst, &x, 1);
362 silc_buffer_pull(dst, 1);
366 case SILC_PARAM_UINT16:
369 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
374 FORMAT_HAS_SPACE(stack, dst, 2);
375 SILC_PUT16_MSB(x, xf);
376 silc_buffer_put(dst, xf, 2);
377 silc_buffer_pull(dst, 2);
381 case SILC_PARAM_UINT32:
384 SilcUInt32 x = va_arg(ap, SilcUInt32);
389 FORMAT_HAS_SPACE(stack, dst, 4);
390 SILC_PUT32_MSB(x, xf);
391 silc_buffer_put(dst, xf, 4);
392 silc_buffer_pull(dst, 4);
396 case SILC_PARAM_UINT64:
399 SilcUInt64 x = va_arg(ap, SilcUInt64);
404 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
405 SILC_PUT64_MSB(x, xf);
406 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
407 silc_buffer_pull(dst, sizeof(SilcUInt64));
411 case SILC_PARAM_SINT8:
413 char x = (char)va_arg(ap, int);
418 FORMAT_HAS_SPACE(stack, dst, 1);
419 silc_buffer_put(dst, (unsigned char *)&x, 1);
420 silc_buffer_pull(dst, 1);
424 case SILC_PARAM_SINT16:
427 SilcInt16 x = (SilcInt16)va_arg(ap, int);
432 FORMAT_HAS_SPACE(stack, dst, 2);
433 SILC_PUT16_MSB(x, xf);
434 silc_buffer_put(dst, xf, 2);
435 silc_buffer_pull(dst, 2);
439 case SILC_PARAM_SINT32:
442 SilcInt32 x = va_arg(ap, SilcInt32);
447 FORMAT_HAS_SPACE(stack, dst, 4);
448 SILC_PUT32_MSB(x, xf);
449 silc_buffer_put(dst, xf, 4);
450 silc_buffer_pull(dst, 4);
454 case SILC_PARAM_SINT64:
457 SilcInt64 x = va_arg(ap, SilcInt64);
462 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
463 SILC_PUT64_MSB(x, xf);
464 silc_buffer_put(dst, xf, sizeof(SilcInt64));
465 silc_buffer_pull(dst, sizeof(SilcInt64));
469 case SILC_PARAM_BUFFER:
470 case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
472 SilcBuffer x = va_arg(ap, SilcBuffer);
478 if (x && silc_buffer_len(x)) {
479 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
480 SILC_PUT32_MSB(silc_buffer_len(x), xf);
481 silc_buffer_put(dst, xf, 4);
482 silc_buffer_pull(dst, 4);
483 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
484 silc_buffer_pull(dst, silc_buffer_len(x));
489 case SILC_PARAM_DELETE:
491 int n = va_arg(ap, int);
497 /* Move all data from tail to data area */
498 if (dst->data != dst->tail) {
500 n = silc_buffer_len(dst);
501 memmove(dst->data, dst->tail, silc_buffer_taillen(dst));
502 silc_buffer_push_tail(dst, n);
503 if (!silc_buffer_srealloc(stack, dst,
504 silc_buffer_truelen(dst) - n))
510 if (n > silc_buffer_len(dst))
513 memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) +
514 silc_buffer_taillen(dst));
515 silc_buffer_push_tail(dst, silc_buffer_len(dst) - n);
516 if (!silc_buffer_srealloc(stack, dst, silc_buffer_truelen(dst) - n))
522 case SILC_PARAM_OFFSET:
524 int offst = va_arg(ap, int);
533 if (offst > silc_buffer_len(dst)) {
534 silc_set_errno(SILC_ERR_OVERFLOW);
537 silc_buffer_pull(dst, offst);
540 silc_buffer_push(dst, -(offst));
546 case SILC_PARAM_OFFSET_START:
549 if (!silc_buffer_push(dst, flen))
554 case SILC_PARAM_OFFSET_END:
557 flen += silc_buffer_len(dst);
558 silc_buffer_pull(dst, silc_buffer_len(dst));
561 case SILC_PARAM_ADVANCE:
572 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
573 "format the data.", fmt));
574 silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
575 "Bad buffer formatting type %d", fmt);
582 SILC_LOG_DEBUG(("Error occured while formatting data"));
583 if (process && !advance)
584 silc_buffer_push(dst, flen);
588 /* Push the buffer back to where it belongs. */
589 if (process && !advance)
590 silc_buffer_push(dst, flen);
594 int silc_buffer_format(SilcBuffer dst, ...)
600 ret = silc_buffer_sformat_vp(NULL, dst, ap);
606 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
608 return silc_buffer_sformat_vp(NULL, dst, ap);
611 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
617 ret = silc_buffer_sformat_vp(stack, dst, ap);
623 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
625 return silc_buffer_sformat_vp_i(stack, dst, ap, TRUE);
628 /****************************** Unformatting ********************************/
630 int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
634 unsigned char *start_ptr = src->data;
636 SilcBool advance = FALSE;
638 /* Parse the arguments by formatting type. */
640 fmt = va_arg(ap, SilcParam);
642 SILC_LOG_DEBUG(("Buffer unformat type %s (%d)",
643 silc_param_string(fmt), fmt));
646 case SILC_PARAM_FUNC:
648 SilcBufferUnformatFunc func;
652 func = va_arg(ap, SilcBufferUnformatFunc);
653 val = va_arg(ap, void **);
654 context = va_arg(ap, void *);
659 tmp_len = func(stack, src, val, context);
663 UNFORMAT_HAS_SPACE(src, tmp_len);
664 silc_buffer_pull(src, tmp_len);
669 case SILC_PARAM_REGEX:
671 const char *regex = va_arg(ap, char *);
672 SilcBufferRegexFlags rflags = va_arg(ap, SilcUInt32);
673 SilcBufferStruct match;
674 SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
675 SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
677 SilcUInt32 inclusive_pos = 0;
678 int matched = 0, ret_len;
689 /* Match for '\n' in the buffer. If not found, treat as line
690 without '\n' (buffer has only one line, or this is last line). */
691 if (silc_regex_buffer(src, "\n", &match, NULL))
692 src->tail = match.tail;
697 ret = silc_regex_buffer(src, regex, &match, NULL);
698 ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
700 if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
701 silc_set_errno(SILC_ERR_NOT_FOUND);
708 if (rflags & SILC_STR_REGEX_NOT)
711 if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
712 /* Advance buffer after match */
713 if (!silc_buffer_pull(src, (match.data - src->data)))
717 if (rflags & SILC_STR_REGEX_INCLUSIVE) {
718 inclusive_pos = src->tail - match.tail;
719 src->tail = match.tail;
722 /* Recursively format */
723 silc_va_copy(cp, ap);
724 ret_len = silc_buffer_sunformat_vp_i(stack, src, cp, TRUE);
729 if (rflags & SILC_STR_REGEX_INCLUSIVE)
730 if (!silc_buffer_pull_tail(src, inclusive_pos))
733 /* Advance buffer after formatting */
734 if (!silc_buffer_pull(src, ret_len))
737 if (match_all && (!match_nl || silc_buffer_len(src) > 1))
742 /* Go to next line, it is at the end of the data area. Adjust
743 the tail area of the target buffer to show rest of the buffer. */
744 if (!silc_buffer_pull(src, (src->tail - src->data)))
746 if (!silc_buffer_pull_tail(src, silc_buffer_taillen(src)))
749 if (silc_buffer_len(src) > 0)
753 /* Skip to the next SILC_PARAM_END */
754 silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE);
759 case SILC_PARAM_UICHAR:
761 unsigned char **x = va_arg(ap, unsigned char **);
762 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
767 UNFORMAT_HAS_SPACE(src, len2);
768 if (silc_likely(len2 && x))
770 silc_buffer_pull(src, len2);
774 case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
776 unsigned char **x = va_arg(ap, unsigned char **);
777 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
782 UNFORMAT_HAS_SPACE(src, len2);
783 if (silc_likely(len2 && x)) {
784 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
785 memcpy(*x, src->data, len2);
787 silc_buffer_pull(src, len2);
791 case SILC_PARAM_UINT8:
793 unsigned char *x = va_arg(ap, unsigned char *);
798 UNFORMAT_HAS_SPACE(src, 1);
801 silc_buffer_pull(src, 1);
805 case SILC_PARAM_UINT16:
807 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
812 UNFORMAT_HAS_SPACE(src, 2);
814 SILC_GET16_MSB(*x, src->data);
815 silc_buffer_pull(src, 2);
819 case SILC_PARAM_UINT32:
821 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
826 UNFORMAT_HAS_SPACE(src, 4);
828 SILC_GET32_MSB(*x, src->data);
829 silc_buffer_pull(src, 4);
833 case SILC_PARAM_UINT64:
835 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
840 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
842 SILC_GET64_MSB(*x, src->data);
843 silc_buffer_pull(src, sizeof(SilcUInt64));
847 case SILC_PARAM_SINT8:
849 char *x = va_arg(ap, char *);
854 UNFORMAT_HAS_SPACE(src, 1);
857 silc_buffer_pull(src, 1);
861 case SILC_PARAM_SINT16:
863 SilcInt16 *x = va_arg(ap, SilcInt16 *);
868 UNFORMAT_HAS_SPACE(src, 2);
870 SILC_GET16_MSB(*x, src->data);
871 silc_buffer_pull(src, 2);
875 case SILC_PARAM_SINT32:
877 SilcInt32 *x = va_arg(ap, SilcInt32 *);
882 UNFORMAT_HAS_SPACE(src, 4);
884 SILC_GET32_MSB(*x, src->data);
885 silc_buffer_pull(src, 4);
889 case SILC_PARAM_SINT64:
891 SilcInt64 *x = va_arg(ap, SilcInt64 *);
896 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
898 SILC_GET64_MSB(*x, src->data);
899 silc_buffer_pull(src, sizeof(SilcInt64));
903 case SILC_PARAM_UI8_STRING:
906 unsigned char **x = va_arg(ap, unsigned char **);
911 UNFORMAT_HAS_SPACE(src, 1);
912 len2 = (SilcUInt8)src->data[0];
913 silc_buffer_pull(src, 1);
914 UNFORMAT_HAS_SPACE(src, len2);
917 silc_buffer_pull(src, len2);
921 case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
924 unsigned char **x = va_arg(ap, unsigned char **);
929 UNFORMAT_HAS_SPACE(src, 1);
930 len2 = (SilcUInt8)src->data[0];
931 silc_buffer_pull(src, 1);
932 UNFORMAT_HAS_SPACE(src, len2);
933 if (silc_likely(x && len2)) {
934 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
935 memcpy(*x, src->data, len2);
937 silc_buffer_pull(src, len2);
941 case SILC_PARAM_UI16_STRING:
944 unsigned char **x = va_arg(ap, unsigned char **);
949 UNFORMAT_HAS_SPACE(src, 2);
950 SILC_GET16_MSB(len2, src->data);
951 silc_buffer_pull(src, 2);
952 UNFORMAT_HAS_SPACE(src, len2);
955 silc_buffer_pull(src, len2);
959 case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
962 unsigned char **x = va_arg(ap, unsigned char **);
967 UNFORMAT_HAS_SPACE(src, 2);
968 SILC_GET16_MSB(len2, src->data);
969 silc_buffer_pull(src, 2);
970 UNFORMAT_HAS_SPACE(src, len2);
971 if (silc_likely(x && len2)) {
972 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
973 memcpy(*x, src->data, len2);
975 silc_buffer_pull(src, len2);
979 case SILC_PARAM_UI32_STRING:
982 unsigned char **x = va_arg(ap, unsigned char **);
987 UNFORMAT_HAS_SPACE(src, 4);
988 SILC_GET32_MSB(len2, src->data);
989 silc_buffer_pull(src, 4);
990 UNFORMAT_HAS_SPACE(src, len2);
993 silc_buffer_pull(src, len2);
997 case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
1000 unsigned char **x = va_arg(ap, unsigned char **);
1005 UNFORMAT_HAS_SPACE(src, 4);
1006 SILC_GET32_MSB(len2, src->data);
1007 silc_buffer_pull(src, 4);
1008 UNFORMAT_HAS_SPACE(src, len2);
1009 if (silc_likely(x && len2)) {
1010 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1011 memcpy(*x, src->data, len2);
1013 silc_buffer_pull(src, len2);
1017 case SILC_PARAM_UI8_NSTRING:
1020 unsigned char **x = va_arg(ap, unsigned char **);
1021 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
1026 UNFORMAT_HAS_SPACE(src, 1);
1027 len2 = (SilcUInt8)src->data[0];
1028 silc_buffer_pull(src, 1);
1029 UNFORMAT_HAS_SPACE(src, len2);
1034 silc_buffer_pull(src, len2);
1038 case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
1041 unsigned char **x = va_arg(ap, unsigned char **);
1042 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
1047 UNFORMAT_HAS_SPACE(src, 1);
1048 len2 = (SilcUInt8)src->data[0];
1049 silc_buffer_pull(src, 1);
1050 UNFORMAT_HAS_SPACE(src, len2);
1054 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1055 memcpy(*x, src->data, len2);
1057 silc_buffer_pull(src, len2);
1061 case SILC_PARAM_UI16_NSTRING:
1064 unsigned char **x = va_arg(ap, unsigned char **);
1065 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
1070 UNFORMAT_HAS_SPACE(src, 2);
1071 SILC_GET16_MSB(len2, src->data);
1072 silc_buffer_pull(src, 2);
1073 UNFORMAT_HAS_SPACE(src, len2);
1078 silc_buffer_pull(src, len2);
1082 case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
1085 unsigned char **x = va_arg(ap, unsigned char **);
1086 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
1091 UNFORMAT_HAS_SPACE(src, 2);
1092 SILC_GET16_MSB(len2, src->data);
1093 silc_buffer_pull(src, 2);
1094 UNFORMAT_HAS_SPACE(src, len2);
1098 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1099 memcpy(*x, src->data, len2);
1101 silc_buffer_pull(src, len2);
1105 case SILC_PARAM_UI32_NSTRING:
1108 unsigned char **x = va_arg(ap, unsigned char **);
1109 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1114 UNFORMAT_HAS_SPACE(src, 4);
1115 SILC_GET32_MSB(len2, src->data);
1116 silc_buffer_pull(src, 4);
1117 UNFORMAT_HAS_SPACE(src, len2);
1122 silc_buffer_pull(src, len2);
1126 case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
1129 unsigned char **x = va_arg(ap, unsigned char **);
1130 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1135 UNFORMAT_HAS_SPACE(src, 4);
1136 SILC_GET32_MSB(len2, src->data);
1137 silc_buffer_pull(src, 4);
1138 UNFORMAT_HAS_SPACE(src, len2);
1141 if (silc_likely(x && len2)) {
1142 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1143 memcpy(*x, src->data, len2);
1145 silc_buffer_pull(src, len2);
1149 case SILC_PARAM_BUFFER:
1151 SilcBuffer x = va_arg(ap, SilcBuffer);
1157 UNFORMAT_HAS_SPACE(src, 4);
1158 SILC_GET32_MSB(len2, src->data);
1159 silc_buffer_pull(src, 4);
1160 UNFORMAT_HAS_SPACE(src, len2);
1161 silc_buffer_set(x, src->data, len2);
1162 silc_buffer_pull(src, len2);
1166 case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
1168 SilcBuffer x = va_arg(ap, SilcBuffer);
1174 UNFORMAT_HAS_SPACE(src, 4);
1175 SILC_GET32_MSB(len2, src->data);
1176 silc_buffer_pull(src, 4);
1177 UNFORMAT_HAS_SPACE(src, len2);
1178 silc_buffer_sformat(stack, x,
1179 SILC_STR_DATA(src->data, len2),
1181 silc_buffer_pull(src, len2);
1185 case SILC_PARAM_OFFSET:
1187 int offst = va_arg(ap, int);
1196 UNFORMAT_HAS_SPACE(src, offst);
1197 silc_buffer_pull(src, offst);
1199 silc_buffer_push(src, -(offst));
1204 case SILC_PARAM_OFFSET_START:
1207 silc_buffer_push(src, (src->data - start_ptr));
1210 case SILC_PARAM_OFFSET_END:
1213 silc_buffer_pull(src, silc_buffer_len(src));
1216 case SILC_PARAM_ADVANCE:
1222 case SILC_PARAM_END:
1226 case SILC_PARAM_DELETE:
1230 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
1231 "format the data.", fmt));
1232 silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
1233 "Bad buffer formatting type %d", fmt);
1240 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
1241 if (process && !advance) {
1242 len = src->data - start_ptr;
1243 silc_buffer_push(src, len);
1248 /* Push the buffer back to the start. */
1249 if (process && !advance) {
1250 len = src->data - start_ptr;
1251 silc_buffer_push(src, len);
1256 int silc_buffer_unformat(SilcBuffer src, ...)
1262 ret = silc_buffer_sunformat_vp(NULL, src, ap);
1268 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
1270 return silc_buffer_sunformat_vp(NULL, src, ap);
1273 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
1279 ret = silc_buffer_sunformat_vp(stack, src, ap);
1285 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
1287 return silc_buffer_sunformat_vp_i(stack, src, ap, TRUE);
1290 /**************************** Utility functions *****************************/
1292 /* Formats strings into a buffer */
1294 int silc_buffer_strformat(SilcBuffer dst, ...)
1296 int len = silc_buffer_truelen(dst);
1297 int hlen = silc_buffer_headlen(dst);
1302 /* Parse the arguments by formatting type. */
1304 char *string = va_arg(va, char *);
1310 if (string == (char *)SILC_PARAM_END)
1313 slen = strlen(string);
1314 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
1315 if (silc_unlikely(!d))
1318 memcpy(dst->head + len, string, slen);
1320 dst->head[len] = '\0';
1323 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
1328 dst->end = dst->head + len;
1329 dst->data = dst->head + hlen;
1330 dst->tail = dst->end;
1336 /* Formats strings into a buffer. Allocates memory from SilcStack. */
1338 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
1340 int len = silc_buffer_truelen(dst);
1341 int hlen = silc_buffer_headlen(dst);
1346 /* Parse the arguments by formatting type. */
1348 char *string = va_arg(va, char *);
1354 if (string == (char *)SILC_PARAM_END)
1357 slen = strlen(string);
1358 d = silc_srealloc(stack, len + 1, dst->head,
1359 sizeof(*dst->head) * (slen + len + 1));
1360 if (silc_unlikely(!d))
1363 memcpy(dst->head + len, string, slen);
1365 dst->head[len] = '\0';
1368 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
1373 dst->end = dst->head + len;
1374 dst->data = dst->head + hlen;
1375 dst->tail = dst->end;