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.
20 #include "silcruntime.h"
22 /************************** Types and definitions ***************************/
24 /* Check that buffer has enough room to format data in it, if not
26 #define FORMAT_HAS_SPACE(s, b, req) \
28 if (silc_unlikely(!silc_buffer_senlarge(s, b, req))) \
33 /* Check that buffer has enough room to format data in it, if not
34 allocate more. This will append, thus not replacing any existing data. */
35 #define FORMAT_HAS_SPACE_APPEND(s, b, req) \
37 if (silc_buffer_len(b) < req) \
38 if (silc_unlikely(!silc_buffer_sappend(s, b, req - silc_buffer_len(b)))) \
43 /* Check that there is data to be unformatted */
44 #define UNFORMAT_HAS_SPACE(b, req) \
46 if (silc_unlikely(req > silc_buffer_len(b))) { \
47 silc_set_errno(SILC_ERR_OVERFLOW); \
50 if (silc_unlikely((req + 1) <= 0)) { \
51 silc_set_errno(SILC_ERR_OVERFLOW); \
56 #if defined(SILC_DEBUG)
57 static const char *silc_param_string(SilcParam fmt)
59 if (fmt == SILC_PARAM_SINT8)
61 if (fmt == SILC_PARAM_UINT8)
63 if (fmt == SILC_PARAM_SINT16)
65 if (fmt == SILC_PARAM_UINT16)
67 if (fmt == SILC_PARAM_SINT32)
69 if (fmt == SILC_PARAM_UINT32)
71 if (fmt == SILC_PARAM_SINT64)
73 if (fmt == SILC_PARAM_UINT64)
75 if (fmt == SILC_PARAM_SICHAR)
77 if (fmt == (SILC_PARAM_SICHAR | SILC_PARAM_ALLOC))
78 return "SICHAR ALLOC";
79 if (fmt == SILC_PARAM_UICHAR)
81 if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_ALLOC))
82 return "UICHAR ALLOC";
83 if (fmt == (SILC_PARAM_UICHAR | SILC_PARAM_REPLACE))
84 return "UICHAR REPLACE";
85 if (fmt == SILC_PARAM_BUFFER)
87 if (fmt == (SILC_PARAM_BUFFER | SILC_PARAM_ALLOC))
88 return "BUFFER ALLOC";
89 if (fmt == SILC_PARAM_PTR)
91 if (fmt == SILC_PARAM_END)
93 if (fmt == SILC_PARAM_UI8_STRING)
95 if (fmt == SILC_PARAM_UI16_STRING)
97 if (fmt == SILC_PARAM_UI32_STRING)
99 if (fmt == SILC_PARAM_UI8_NSTRING)
101 if (fmt == SILC_PARAM_UI16_NSTRING)
102 return "UI16_STRING";
103 if (fmt == SILC_PARAM_UI32_NSTRING)
104 return "UI32_STRING";
105 if (fmt == (SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC))
106 return "UI8_STRING ALLOC";
107 if (fmt == (SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC))
108 return "UI16_STRING ALLOC";
109 if (fmt == (SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC))
110 return "UI32_STRING ALLOC";
111 if (fmt == (SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC))
112 return "UI8_STRING ALLOC";
113 if (fmt == (SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC))
114 return "UI16_STRING ALLOC";
115 if (fmt == (SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC))
116 return "UI32_STRING";
117 if (fmt == SILC_PARAM_OFFSET)
119 if (fmt == SILC_PARAM_ADVANCE)
121 if (fmt == SILC_PARAM_FUNC)
123 if (fmt == SILC_PARAM_REGEX)
125 if (fmt == SILC_PARAM_OFFSET_START)
126 return "OFFSET_START";
127 if (fmt == SILC_PARAM_OFFSET_END)
129 if (fmt == SILC_PARAM_DELETE)
133 #endif /* SILC_DEBUG */
135 /******************************* Formatting *********************************/
137 int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
142 SilcBool advance = FALSE;
144 /* Parse the arguments by formatting type. */
146 fmt = va_arg(ap, SilcParam);
148 #if defined(SILC_DEBUG)
150 SILC_LOG_DEBUG(("Buffer format type %s (%d)",
151 silc_param_string(fmt), fmt));
152 #endif /* SILC_DEBUG */
155 case SILC_PARAM_FUNC:
157 SilcBufferFormatFunc func;
162 func = va_arg(ap, SilcBufferFormatFunc);
163 val = va_arg(ap, void *);
164 context = va_arg(ap, void *);
169 tmp_len = func(stack, dst, val, context);
173 silc_buffer_pull(dst, tmp_len);
179 case SILC_PARAM_REGEX:
181 const char *regex = va_arg(ap, char *);
182 SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags);
183 SilcBufferStruct match;
184 SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
185 SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
187 SilcUInt32 inclusive_pos = 0;
188 int matched = 0, ret_len;
199 /* Match for '\n' in the buffer. If not found, treat as line
200 without '\n' (buffer has only one line, or this is last line). */
201 if (silc_regex_buffer(dst, "\n", &match, NULL))
202 dst->tail = match.tail;
207 ret = silc_regex_buffer(dst, regex, &match, NULL);
208 ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
210 if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
211 silc_set_errno(SILC_ERR_NOT_FOUND);
218 if (rflags & SILC_STR_REGEX_NOT)
221 if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
222 /* Advance buffer after match */
223 flen += (match.data - dst->data);
224 if (!silc_buffer_pull(dst, (match.data - dst->data)))
228 if (rflags & SILC_STR_REGEX_INCLUSIVE) {
229 inclusive_pos = dst->tail - match.tail;
230 dst->tail = match.tail;
233 /* Recursively format */
234 silc_va_copy(cp, ap);
235 ret_len = silc_buffer_sformat_vp_i(stack, dst, cp, TRUE);
240 if (rflags & SILC_STR_REGEX_INCLUSIVE)
241 if (!silc_buffer_pull_tail(dst, inclusive_pos))
244 /* Advance buffer after formatting */
246 if (!silc_buffer_pull(dst, ret_len))
249 if (match_all && (!match_nl || silc_buffer_len(dst) > 1))
254 /* Go to next line, it is at the end of the data area. Adjust
255 the tail area of the target buffer to show rest of the buffer. */
256 flen += (dst->tail - dst->data);
257 if (!silc_buffer_pull(dst, (dst->tail - dst->data)))
259 if (!silc_buffer_pull_tail(dst, silc_buffer_taillen(dst)))
262 if (silc_buffer_len(dst) > 0)
266 /* Skip to the next SILC_PARAM_END */
267 silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE);
271 case SILC_PARAM_UI8_STRING:
272 case SILC_PARAM_UI16_STRING:
273 case SILC_PARAM_UI32_STRING:
274 case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
275 case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
276 case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
278 char *x = va_arg(ap, char *);
279 SilcUInt32 tmp_len = x ? strlen(x) : 0;
285 FORMAT_HAS_SPACE(stack, dst, tmp_len);
286 silc_buffer_put(dst, (unsigned char *)x, tmp_len);
287 silc_buffer_pull(dst, tmp_len);
292 case SILC_PARAM_UICHAR | SILC_PARAM_REPLACE:
294 unsigned char *x = va_arg(ap, unsigned char *);
295 SilcUInt32 x_len = va_arg(ap, SilcUInt32);
303 if (silc_buffer_len(dst) == x_len) {
306 silc_buffer_put(dst, x, x_len);
307 silc_buffer_pull(dst, x_len);
310 } else if (silc_buffer_len(dst) < x_len) {
313 FORMAT_HAS_SPACE_APPEND(stack, dst, x_len);
314 silc_buffer_put(dst, x, x_len);
315 silc_buffer_pull(dst, x_len);
320 silc_buffer_put(dst, x, x_len);
321 silc_buffer_pull(dst, x_len);
329 case SILC_PARAM_UI8_NSTRING:
330 case SILC_PARAM_UI16_NSTRING:
331 case SILC_PARAM_UI32_NSTRING:
332 case SILC_PARAM_UICHAR:
333 case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
334 case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
335 case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
336 case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
338 unsigned char *x = va_arg(ap, unsigned char *);
339 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
345 FORMAT_HAS_SPACE(stack, dst, tmp_len);
346 silc_buffer_put(dst, x, tmp_len);
347 silc_buffer_pull(dst, tmp_len);
352 case SILC_PARAM_UINT8:
354 unsigned char x = (unsigned char)va_arg(ap, int);
359 FORMAT_HAS_SPACE(stack, dst, 1);
360 silc_buffer_put(dst, &x, 1);
361 silc_buffer_pull(dst, 1);
365 case SILC_PARAM_UINT16:
368 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
373 FORMAT_HAS_SPACE(stack, dst, 2);
374 SILC_PUT16_MSB(x, xf);
375 silc_buffer_put(dst, xf, 2);
376 silc_buffer_pull(dst, 2);
380 case SILC_PARAM_UINT32:
383 SilcUInt32 x = va_arg(ap, SilcUInt32);
388 FORMAT_HAS_SPACE(stack, dst, 4);
389 SILC_PUT32_MSB(x, xf);
390 silc_buffer_put(dst, xf, 4);
391 silc_buffer_pull(dst, 4);
395 case SILC_PARAM_UINT64:
398 SilcUInt64 x = va_arg(ap, SilcUInt64);
403 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
404 SILC_PUT64_MSB(x, xf);
405 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
406 silc_buffer_pull(dst, sizeof(SilcUInt64));
410 case SILC_PARAM_SINT8:
412 char x = (char)va_arg(ap, int);
417 FORMAT_HAS_SPACE(stack, dst, 1);
418 silc_buffer_put(dst, (unsigned char *)&x, 1);
419 silc_buffer_pull(dst, 1);
423 case SILC_PARAM_SINT16:
426 SilcInt16 x = (SilcInt16)va_arg(ap, int);
431 FORMAT_HAS_SPACE(stack, dst, 2);
432 SILC_PUT16_MSB(x, xf);
433 silc_buffer_put(dst, xf, 2);
434 silc_buffer_pull(dst, 2);
438 case SILC_PARAM_SINT32:
441 SilcInt32 x = va_arg(ap, SilcInt32);
446 FORMAT_HAS_SPACE(stack, dst, 4);
447 SILC_PUT32_MSB(x, xf);
448 silc_buffer_put(dst, xf, 4);
449 silc_buffer_pull(dst, 4);
453 case SILC_PARAM_SINT64:
456 SilcInt64 x = va_arg(ap, SilcInt64);
461 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
462 SILC_PUT64_MSB(x, xf);
463 silc_buffer_put(dst, xf, sizeof(SilcInt64));
464 silc_buffer_pull(dst, sizeof(SilcInt64));
468 case SILC_PARAM_BUFFER:
469 case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
471 SilcBuffer x = va_arg(ap, SilcBuffer);
477 if (x && silc_buffer_len(x)) {
478 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
479 SILC_PUT32_MSB(silc_buffer_len(x), xf);
480 silc_buffer_put(dst, xf, 4);
481 silc_buffer_pull(dst, 4);
482 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
483 silc_buffer_pull(dst, silc_buffer_len(x));
488 case SILC_PARAM_DELETE:
490 int n = va_arg(ap, int);
496 /* Move all data from tail to data area */
497 if (dst->data != dst->tail) {
499 n = silc_buffer_len(dst);
500 memmove(dst->data, dst->tail, silc_buffer_taillen(dst));
501 silc_buffer_push_tail(dst, n);
502 if (!silc_buffer_srealloc(stack, dst,
503 silc_buffer_truelen(dst) - n))
509 if (n > silc_buffer_len(dst))
512 memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) +
513 silc_buffer_taillen(dst));
514 silc_buffer_push_tail(dst, silc_buffer_len(dst) - n);
515 if (!silc_buffer_srealloc(stack, dst, silc_buffer_truelen(dst) - n))
521 case SILC_PARAM_OFFSET:
523 int offst = va_arg(ap, int);
532 if (offst > silc_buffer_len(dst)) {
533 silc_set_errno(SILC_ERR_OVERFLOW);
536 silc_buffer_pull(dst, offst);
539 silc_buffer_push(dst, -(offst));
545 case SILC_PARAM_OFFSET_START:
548 if (!silc_buffer_push(dst, flen))
553 case SILC_PARAM_OFFSET_END:
556 flen += silc_buffer_len(dst);
557 silc_buffer_pull(dst, silc_buffer_len(dst));
560 case SILC_PARAM_ADVANCE:
571 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
572 "format the data.", fmt));
573 silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
574 "Bad buffer formatting type %d", fmt);
581 SILC_LOG_DEBUG(("Error occured while formatting data"));
582 if (process && !advance)
583 silc_buffer_push(dst, flen);
587 /* Push the buffer back to where it belongs. */
588 if (process && !advance)
589 silc_buffer_push(dst, flen);
593 int silc_buffer_format(SilcBuffer dst, ...)
599 ret = silc_buffer_sformat_vp(NULL, dst, ap);
605 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
607 return silc_buffer_sformat_vp(NULL, dst, ap);
610 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
616 ret = silc_buffer_sformat_vp(stack, dst, ap);
622 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
624 return silc_buffer_sformat_vp_i(stack, dst, ap, TRUE);
627 /****************************** Unformatting ********************************/
629 int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
633 unsigned char *start_ptr = src->data;
635 SilcBool advance = FALSE;
637 /* Parse the arguments by formatting type. */
639 fmt = va_arg(ap, SilcParam);
641 SILC_LOG_DEBUG(("Buffer unformat type %s (%d)",
642 silc_param_string(fmt), fmt));
645 case SILC_PARAM_FUNC:
647 SilcBufferUnformatFunc func;
651 func = va_arg(ap, SilcBufferUnformatFunc);
652 val = va_arg(ap, void **);
653 context = va_arg(ap, void *);
658 tmp_len = func(stack, src, val, context);
662 UNFORMAT_HAS_SPACE(src, tmp_len);
663 silc_buffer_pull(src, tmp_len);
668 case SILC_PARAM_REGEX:
670 const char *regex = va_arg(ap, char *);
671 SilcBufferRegexFlags rflags = va_arg(ap, SilcBufferRegexFlags);
672 SilcBufferStruct match;
673 SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
674 SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
676 SilcUInt32 inclusive_pos = 0;
677 int matched = 0, ret_len;
688 /* Match for '\n' in the buffer. If not found, treat as line
689 without '\n' (buffer has only one line, or this is last line). */
690 if (silc_regex_buffer(src, "\n", &match, NULL))
691 src->tail = match.tail;
696 ret = silc_regex_buffer(src, regex, &match, NULL);
697 ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
699 if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
700 silc_set_errno(SILC_ERR_NOT_FOUND);
707 if (rflags & SILC_STR_REGEX_NOT)
710 if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
711 /* Advance buffer after match */
712 if (!silc_buffer_pull(src, (match.data - src->data)))
716 if (rflags & SILC_STR_REGEX_INCLUSIVE) {
717 inclusive_pos = src->tail - match.tail;
718 src->tail = match.tail;
721 /* Recursively format */
722 silc_va_copy(cp, ap);
723 ret_len = silc_buffer_sunformat_vp_i(stack, src, cp, TRUE);
728 if (rflags & SILC_STR_REGEX_INCLUSIVE)
729 if (!silc_buffer_pull_tail(src, inclusive_pos))
732 /* Advance buffer after formatting */
733 if (!silc_buffer_pull(src, ret_len))
736 if (match_all && (!match_nl || silc_buffer_len(src) > 1))
741 /* Go to next line, it is at the end of the data area. Adjust
742 the tail area of the target buffer to show rest of the buffer. */
743 if (!silc_buffer_pull(src, (src->tail - src->data)))
745 if (!silc_buffer_pull_tail(src, silc_buffer_taillen(src)))
748 if (silc_buffer_len(src) > 0)
752 /* Skip to the next SILC_PARAM_END */
753 silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE);
758 case SILC_PARAM_UICHAR:
760 unsigned char **x = va_arg(ap, unsigned char **);
761 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
766 UNFORMAT_HAS_SPACE(src, len2);
767 if (silc_likely(len2 && x))
769 silc_buffer_pull(src, len2);
773 case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
775 unsigned char **x = va_arg(ap, unsigned char **);
776 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
781 UNFORMAT_HAS_SPACE(src, len2);
782 if (silc_likely(len2 && x)) {
783 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
784 memcpy(*x, src->data, len2);
786 silc_buffer_pull(src, len2);
790 case SILC_PARAM_UINT8:
792 unsigned char *x = va_arg(ap, unsigned char *);
797 UNFORMAT_HAS_SPACE(src, 1);
800 silc_buffer_pull(src, 1);
804 case SILC_PARAM_UINT16:
806 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
811 UNFORMAT_HAS_SPACE(src, 2);
813 SILC_GET16_MSB(*x, src->data);
814 silc_buffer_pull(src, 2);
818 case SILC_PARAM_UINT32:
820 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
825 UNFORMAT_HAS_SPACE(src, 4);
827 SILC_GET32_MSB(*x, src->data);
828 silc_buffer_pull(src, 4);
832 case SILC_PARAM_UINT64:
834 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
839 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
841 SILC_GET64_MSB(*x, src->data);
842 silc_buffer_pull(src, sizeof(SilcUInt64));
846 case SILC_PARAM_SINT8:
848 char *x = va_arg(ap, char *);
853 UNFORMAT_HAS_SPACE(src, 1);
856 silc_buffer_pull(src, 1);
860 case SILC_PARAM_SINT16:
862 SilcInt16 *x = va_arg(ap, SilcInt16 *);
867 UNFORMAT_HAS_SPACE(src, 2);
869 SILC_GET16_MSB(*x, src->data);
870 silc_buffer_pull(src, 2);
874 case SILC_PARAM_SINT32:
876 SilcInt32 *x = va_arg(ap, SilcInt32 *);
881 UNFORMAT_HAS_SPACE(src, 4);
883 SILC_GET32_MSB(*x, src->data);
884 silc_buffer_pull(src, 4);
888 case SILC_PARAM_SINT64:
890 SilcInt64 *x = va_arg(ap, SilcInt64 *);
895 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
897 SILC_GET64_MSB(*x, src->data);
898 silc_buffer_pull(src, sizeof(SilcInt64));
902 case SILC_PARAM_UI8_STRING:
905 unsigned char **x = va_arg(ap, unsigned char **);
910 UNFORMAT_HAS_SPACE(src, 1);
911 len2 = (SilcUInt8)src->data[0];
912 silc_buffer_pull(src, 1);
913 UNFORMAT_HAS_SPACE(src, len2);
916 silc_buffer_pull(src, len2);
920 case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
923 unsigned char **x = va_arg(ap, unsigned char **);
928 UNFORMAT_HAS_SPACE(src, 1);
929 len2 = (SilcUInt8)src->data[0];
930 silc_buffer_pull(src, 1);
931 UNFORMAT_HAS_SPACE(src, len2);
932 if (silc_likely(x && len2)) {
933 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
934 memcpy(*x, src->data, len2);
936 silc_buffer_pull(src, len2);
940 case SILC_PARAM_UI16_STRING:
943 unsigned char **x = va_arg(ap, unsigned char **);
948 UNFORMAT_HAS_SPACE(src, 2);
949 SILC_GET16_MSB(len2, src->data);
950 silc_buffer_pull(src, 2);
951 UNFORMAT_HAS_SPACE(src, len2);
954 silc_buffer_pull(src, len2);
958 case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
961 unsigned char **x = va_arg(ap, unsigned char **);
966 UNFORMAT_HAS_SPACE(src, 2);
967 SILC_GET16_MSB(len2, src->data);
968 silc_buffer_pull(src, 2);
969 UNFORMAT_HAS_SPACE(src, len2);
970 if (silc_likely(x && len2)) {
971 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
972 memcpy(*x, src->data, len2);
974 silc_buffer_pull(src, len2);
978 case SILC_PARAM_UI32_STRING:
981 unsigned char **x = va_arg(ap, unsigned char **);
986 UNFORMAT_HAS_SPACE(src, 4);
987 SILC_GET32_MSB(len2, src->data);
988 silc_buffer_pull(src, 4);
989 UNFORMAT_HAS_SPACE(src, len2);
992 silc_buffer_pull(src, len2);
996 case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
999 unsigned char **x = va_arg(ap, unsigned char **);
1004 UNFORMAT_HAS_SPACE(src, 4);
1005 SILC_GET32_MSB(len2, src->data);
1006 silc_buffer_pull(src, 4);
1007 UNFORMAT_HAS_SPACE(src, len2);
1008 if (silc_likely(x && len2)) {
1009 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1010 memcpy(*x, src->data, len2);
1012 silc_buffer_pull(src, len2);
1016 case SILC_PARAM_UI8_NSTRING:
1019 unsigned char **x = va_arg(ap, unsigned char **);
1020 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
1025 UNFORMAT_HAS_SPACE(src, 1);
1026 len2 = (SilcUInt8)src->data[0];
1027 silc_buffer_pull(src, 1);
1028 UNFORMAT_HAS_SPACE(src, len2);
1033 silc_buffer_pull(src, len2);
1037 case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
1040 unsigned char **x = va_arg(ap, unsigned char **);
1041 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
1046 UNFORMAT_HAS_SPACE(src, 1);
1047 len2 = (SilcUInt8)src->data[0];
1048 silc_buffer_pull(src, 1);
1049 UNFORMAT_HAS_SPACE(src, len2);
1053 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1054 memcpy(*x, src->data, len2);
1056 silc_buffer_pull(src, len2);
1060 case SILC_PARAM_UI16_NSTRING:
1063 unsigned char **x = va_arg(ap, unsigned char **);
1064 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
1069 UNFORMAT_HAS_SPACE(src, 2);
1070 SILC_GET16_MSB(len2, src->data);
1071 silc_buffer_pull(src, 2);
1072 UNFORMAT_HAS_SPACE(src, len2);
1077 silc_buffer_pull(src, len2);
1081 case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
1084 unsigned char **x = va_arg(ap, unsigned char **);
1085 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
1090 UNFORMAT_HAS_SPACE(src, 2);
1091 SILC_GET16_MSB(len2, src->data);
1092 silc_buffer_pull(src, 2);
1093 UNFORMAT_HAS_SPACE(src, len2);
1097 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1098 memcpy(*x, src->data, len2);
1100 silc_buffer_pull(src, len2);
1104 case SILC_PARAM_UI32_NSTRING:
1107 unsigned char **x = va_arg(ap, unsigned char **);
1108 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1113 UNFORMAT_HAS_SPACE(src, 4);
1114 SILC_GET32_MSB(len2, src->data);
1115 silc_buffer_pull(src, 4);
1116 UNFORMAT_HAS_SPACE(src, len2);
1121 silc_buffer_pull(src, len2);
1125 case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
1128 unsigned char **x = va_arg(ap, unsigned char **);
1129 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1134 UNFORMAT_HAS_SPACE(src, 4);
1135 SILC_GET32_MSB(len2, src->data);
1136 silc_buffer_pull(src, 4);
1137 UNFORMAT_HAS_SPACE(src, len2);
1140 if (silc_likely(x && len2)) {
1141 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1142 memcpy(*x, src->data, len2);
1144 silc_buffer_pull(src, len2);
1148 case SILC_PARAM_BUFFER:
1150 SilcBuffer x = va_arg(ap, SilcBuffer);
1156 UNFORMAT_HAS_SPACE(src, 4);
1157 SILC_GET32_MSB(len2, src->data);
1158 silc_buffer_pull(src, 4);
1159 UNFORMAT_HAS_SPACE(src, len2);
1160 silc_buffer_set(x, src->data, len2);
1161 silc_buffer_pull(src, len2);
1165 case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
1167 SilcBuffer x = va_arg(ap, SilcBuffer);
1173 UNFORMAT_HAS_SPACE(src, 4);
1174 SILC_GET32_MSB(len2, src->data);
1175 silc_buffer_pull(src, 4);
1176 UNFORMAT_HAS_SPACE(src, len2);
1177 silc_buffer_sformat(stack, x,
1178 SILC_STR_DATA(src->data, len2),
1180 silc_buffer_pull(src, len2);
1184 case SILC_PARAM_OFFSET:
1186 int offst = va_arg(ap, int);
1195 UNFORMAT_HAS_SPACE(src, offst);
1196 silc_buffer_pull(src, offst);
1198 silc_buffer_push(src, -(offst));
1203 case SILC_PARAM_OFFSET_START:
1206 silc_buffer_push(src, (src->data - start_ptr));
1209 case SILC_PARAM_OFFSET_END:
1212 silc_buffer_pull(src, silc_buffer_len(src));
1215 case SILC_PARAM_ADVANCE:
1221 case SILC_PARAM_END:
1225 case SILC_PARAM_DELETE:
1229 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
1230 "format the data.", fmt));
1231 silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
1232 "Bad buffer formatting type %d", fmt);
1239 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
1240 if (process && !advance) {
1241 len = src->data - start_ptr;
1242 silc_buffer_push(src, len);
1247 len = src->data - start_ptr;
1249 /* Push the buffer back to the start. */
1250 if (process && !advance)
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;