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));
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));
974 memcpy(*x, src->data, len2);
976 silc_buffer_pull(src, len2);
980 case SILC_PARAM_UI32_STRING:
983 unsigned char **x = va_arg(ap, unsigned char **);
988 UNFORMAT_HAS_SPACE(src, 4);
989 SILC_GET32_MSB(len2, src->data);
990 silc_buffer_pull(src, 4);
991 UNFORMAT_HAS_SPACE(src, len2);
994 silc_buffer_pull(src, len2);
998 case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
1001 unsigned char **x = va_arg(ap, unsigned char **);
1006 UNFORMAT_HAS_SPACE(src, 4);
1007 SILC_GET32_MSB(len2, src->data);
1008 silc_buffer_pull(src, 4);
1009 UNFORMAT_HAS_SPACE(src, len2);
1010 if (silc_likely(x && len2)) {
1011 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1013 memcpy(*x, src->data, len2);
1015 silc_buffer_pull(src, len2);
1019 case SILC_PARAM_UI8_NSTRING:
1022 unsigned char **x = va_arg(ap, unsigned char **);
1023 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
1028 UNFORMAT_HAS_SPACE(src, 1);
1029 len2 = (SilcUInt8)src->data[0];
1030 silc_buffer_pull(src, 1);
1031 UNFORMAT_HAS_SPACE(src, len2);
1036 silc_buffer_pull(src, len2);
1040 case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
1043 unsigned char **x = va_arg(ap, unsigned char **);
1044 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
1049 UNFORMAT_HAS_SPACE(src, 1);
1050 len2 = (SilcUInt8)src->data[0];
1051 silc_buffer_pull(src, 1);
1052 UNFORMAT_HAS_SPACE(src, len2);
1056 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1057 memcpy(*x, src->data, len2);
1059 silc_buffer_pull(src, len2);
1063 case SILC_PARAM_UI16_NSTRING:
1066 unsigned char **x = va_arg(ap, unsigned char **);
1067 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
1072 UNFORMAT_HAS_SPACE(src, 2);
1073 SILC_GET16_MSB(len2, src->data);
1074 silc_buffer_pull(src, 2);
1075 UNFORMAT_HAS_SPACE(src, len2);
1080 silc_buffer_pull(src, len2);
1084 case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
1087 unsigned char **x = va_arg(ap, unsigned char **);
1088 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
1093 UNFORMAT_HAS_SPACE(src, 2);
1094 SILC_GET16_MSB(len2, src->data);
1095 silc_buffer_pull(src, 2);
1096 UNFORMAT_HAS_SPACE(src, len2);
1100 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1102 memcpy(*x, src->data, len2);
1104 silc_buffer_pull(src, len2);
1108 case SILC_PARAM_UI32_NSTRING:
1111 unsigned char **x = va_arg(ap, unsigned char **);
1112 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1117 UNFORMAT_HAS_SPACE(src, 4);
1118 SILC_GET32_MSB(len2, src->data);
1119 silc_buffer_pull(src, 4);
1120 UNFORMAT_HAS_SPACE(src, len2);
1125 silc_buffer_pull(src, len2);
1129 case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
1132 unsigned char **x = va_arg(ap, unsigned char **);
1133 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1138 UNFORMAT_HAS_SPACE(src, 4);
1139 SILC_GET32_MSB(len2, src->data);
1140 silc_buffer_pull(src, 4);
1141 UNFORMAT_HAS_SPACE(src, len2);
1144 if (silc_likely(x && len2)) {
1145 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1146 memcpy(*x, src->data, len2);
1148 silc_buffer_pull(src, len2);
1152 case SILC_PARAM_BUFFER:
1154 SilcBuffer x = va_arg(ap, SilcBuffer);
1160 UNFORMAT_HAS_SPACE(src, 4);
1161 SILC_GET32_MSB(len2, src->data);
1162 silc_buffer_pull(src, 4);
1163 UNFORMAT_HAS_SPACE(src, len2);
1164 silc_buffer_set(x, src->data, len2);
1165 silc_buffer_pull(src, len2);
1169 case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
1171 SilcBuffer x = va_arg(ap, SilcBuffer);
1177 UNFORMAT_HAS_SPACE(src, 4);
1178 SILC_GET32_MSB(len2, src->data);
1179 silc_buffer_pull(src, 4);
1180 UNFORMAT_HAS_SPACE(src, len2);
1181 if (silc_buffer_sformat(stack, x,
1182 SILC_STR_DATA(src->data, len2),
1185 silc_buffer_pull(src, len2);
1189 case SILC_PARAM_OFFSET:
1191 int offst = va_arg(ap, int);
1200 UNFORMAT_HAS_SPACE(src, offst);
1201 silc_buffer_pull(src, offst);
1203 silc_buffer_push(src, -(offst));
1208 case SILC_PARAM_OFFSET_START:
1211 silc_buffer_push(src, (src->data - start_ptr));
1214 case SILC_PARAM_OFFSET_END:
1217 silc_buffer_pull(src, silc_buffer_len(src));
1220 case SILC_PARAM_ADVANCE:
1226 case SILC_PARAM_END:
1230 case SILC_PARAM_DELETE:
1234 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
1235 "format the data.", fmt));
1236 silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
1237 "Bad buffer formatting type %d", fmt);
1244 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
1245 if (process && !advance) {
1246 len = src->data - start_ptr;
1247 silc_buffer_push(src, len);
1252 len = src->data - start_ptr;
1254 /* Push the buffer back to the start. */
1255 if (process && !advance)
1256 silc_buffer_push(src, len);
1261 int silc_buffer_unformat(SilcBuffer src, ...)
1267 ret = silc_buffer_sunformat_vp(NULL, src, ap);
1273 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
1275 return silc_buffer_sunformat_vp(NULL, src, ap);
1278 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
1284 ret = silc_buffer_sunformat_vp(stack, src, ap);
1290 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
1292 return silc_buffer_sunformat_vp_i(stack, src, ap, TRUE);
1295 /**************************** Utility functions *****************************/
1297 /* Formats strings into a buffer */
1299 int silc_buffer_strformat(SilcBuffer dst, ...)
1301 int len = silc_buffer_truelen(dst);
1302 int hlen = silc_buffer_headlen(dst);
1307 /* Parse the arguments by formatting type. */
1309 char *string = va_arg(va, char *);
1315 if (string == (char *)SILC_PARAM_END)
1318 slen = strlen(string);
1319 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
1320 if (silc_unlikely(!d))
1323 memcpy(dst->head + len, string, slen);
1325 dst->head[len] = '\0';
1328 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
1333 dst->end = dst->head + len;
1334 dst->data = dst->head + hlen;
1335 dst->tail = dst->end;
1341 /* Formats strings into a buffer. Allocates memory from SilcStack. */
1343 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
1345 int len = silc_buffer_truelen(dst);
1346 int hlen = silc_buffer_headlen(dst);
1351 /* Parse the arguments by formatting type. */
1353 char *string = va_arg(va, char *);
1359 if (string == (char *)SILC_PARAM_END)
1362 slen = strlen(string);
1363 d = silc_srealloc(stack, len + 1, dst->head,
1364 sizeof(*dst->head) * (slen + len + 1));
1365 if (silc_unlikely(!d))
1368 memcpy(dst->head + len, string, slen);
1370 dst->head[len] = '\0';
1373 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
1378 dst->end = dst->head + len;
1379 dst->data = dst->head + hlen;
1380 dst->tail = dst->end;