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); \
58 /******************************* Formatting *********************************/
60 int silc_buffer_sformat_vp_i(SilcStack stack, SilcBuffer dst, va_list ap,
65 SilcBool advance = FALSE;
67 /* Parse the arguments by formatting type. */
69 fmt = va_arg(ap, SilcParam);
71 SILC_LOG_DEBUG(("Buffer format type %d", fmt));
76 SilcBufferFormatFunc func;
81 func = va_arg(ap, SilcBufferFormatFunc);
82 val = va_arg(ap, void *);
83 context = va_arg(ap, void *);
88 tmp_len = func(stack, dst, val, context);
92 silc_buffer_pull(dst, tmp_len);
98 case SILC_PARAM_REGEX:
100 const char *regex = va_arg(ap, char *);
101 SilcBufferRegexFlags rflags = va_arg(ap, SilcUInt32);
102 SilcBufferStruct match;
103 SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
104 SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
106 SilcUInt32 saved_pos = 0, inclusive_pos = 0;
107 int matched = 0, ret_len;
118 /* Match for '\n' in the buffer. If not found, treat as line
119 without '\n' (buffer has only one line, or this is last line). */
120 saved_pos = silc_buffer_headlen(dst) + silc_buffer_len(dst);
121 if (silc_regex_buffer(dst, "\n", &match, NULL))
122 dst->tail = match.tail;
127 ret = silc_regex_buffer(dst, regex, &match, NULL);
128 ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
130 if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
131 silc_set_errno(SILC_ERR_NOT_FOUND);
138 if (rflags & SILC_STR_REGEX_NOT)
141 if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
142 /* Advance buffer after match */
143 flen += (match.data - dst->data);
144 if (!silc_buffer_pull(dst, (match.data - dst->data)))
148 if (rflags & SILC_STR_REGEX_INCLUSIVE) {
149 inclusive_pos = dst->tail - match.tail;
150 dst->tail = match.tail;
153 /* Recursively format */
154 silc_va_copy(cp, ap);
155 ret_len = silc_buffer_sformat_vp_i(stack, dst, cp, TRUE);
160 if (rflags & SILC_STR_REGEX_INCLUSIVE)
161 if (!silc_buffer_pull_tail(dst, inclusive_pos))
164 /* Advance buffer after formatting */
166 if (!silc_buffer_pull(dst, ret_len))
169 if (match_all && (!match_nl || silc_buffer_len(dst) > 1))
174 /* Go to next line, it is at the end of the data area. Adjust
175 the tail area of the target buffer to show rest of the buffer. */
176 flen += (dst->tail - dst->data);
177 if (!silc_buffer_pull(dst, (dst->tail - dst->data)))
179 if (!silc_buffer_pull_tail(dst, (saved_pos -
180 silc_buffer_headlen(dst) +
181 silc_buffer_len(dst))))
184 if (silc_buffer_len(dst) > 0)
188 /* Skip to the next SILC_PARAM_END */
189 silc_buffer_sformat_vp_i(NULL, NULL, ap, FALSE);
193 case SILC_PARAM_UI8_STRING:
194 case SILC_PARAM_UI16_STRING:
195 case SILC_PARAM_UI32_STRING:
196 case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
197 case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
198 case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
200 char *x = va_arg(ap, char *);
201 SilcUInt32 tmp_len = x ? strlen(x) : 0;
207 FORMAT_HAS_SPACE(stack, dst, tmp_len);
208 silc_buffer_put(dst, x, tmp_len);
209 silc_buffer_pull(dst, tmp_len);
214 case SILC_PARAM_UI8_STRING | SILC_PARAM_APPEND:
215 case SILC_PARAM_UI16_STRING | SILC_PARAM_APPEND:
216 case SILC_PARAM_UI32_STRING | SILC_PARAM_APPEND:
218 char *x = va_arg(ap, char *);
219 SilcUInt32 tmp_len = x ? strlen(x) : 0;
225 FORMAT_HAS_SPACE_APPEND(stack, dst, tmp_len);
226 silc_buffer_put(dst, x, tmp_len);
227 silc_buffer_pull(dst, tmp_len);
232 case SILC_PARAM_UI8_NSTRING:
233 case SILC_PARAM_UI16_NSTRING:
234 case SILC_PARAM_UI32_NSTRING:
235 case SILC_PARAM_UICHAR:
236 case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
237 case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
238 case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
239 case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
241 unsigned char *x = va_arg(ap, unsigned char *);
242 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
248 FORMAT_HAS_SPACE(stack, dst, tmp_len);
249 silc_buffer_put(dst, x, tmp_len);
250 silc_buffer_pull(dst, tmp_len);
255 case SILC_PARAM_UINT8:
257 unsigned char x = (unsigned char)va_arg(ap, int);
262 FORMAT_HAS_SPACE(stack, dst, 1);
263 silc_buffer_put(dst, &x, 1);
264 silc_buffer_pull(dst, 1);
268 case SILC_PARAM_UINT16:
271 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
276 FORMAT_HAS_SPACE(stack, dst, 2);
277 SILC_PUT16_MSB(x, xf);
278 silc_buffer_put(dst, xf, 2);
279 silc_buffer_pull(dst, 2);
283 case SILC_PARAM_UINT32:
286 SilcUInt32 x = va_arg(ap, SilcUInt32);
291 FORMAT_HAS_SPACE(stack, dst, 4);
292 SILC_PUT32_MSB(x, xf);
293 silc_buffer_put(dst, xf, 4);
294 silc_buffer_pull(dst, 4);
298 case SILC_PARAM_UINT64:
301 SilcUInt64 x = va_arg(ap, SilcUInt64);
306 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
307 SILC_PUT64_MSB(x, xf);
308 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
309 silc_buffer_pull(dst, sizeof(SilcUInt64));
313 case SILC_PARAM_SINT8:
315 char x = (char)va_arg(ap, int);
320 FORMAT_HAS_SPACE(stack, dst, 1);
321 silc_buffer_put(dst, (unsigned char *)&x, 1);
322 silc_buffer_pull(dst, 1);
326 case SILC_PARAM_SINT16:
329 SilcInt16 x = (SilcInt16)va_arg(ap, int);
334 FORMAT_HAS_SPACE(stack, dst, 2);
335 SILC_PUT16_MSB(x, xf);
336 silc_buffer_put(dst, xf, 2);
337 silc_buffer_pull(dst, 2);
341 case SILC_PARAM_SINT32:
344 SilcInt32 x = va_arg(ap, SilcInt32);
349 FORMAT_HAS_SPACE(stack, dst, 4);
350 SILC_PUT32_MSB(x, xf);
351 silc_buffer_put(dst, xf, 4);
352 silc_buffer_pull(dst, 4);
356 case SILC_PARAM_SINT64:
359 SilcInt64 x = va_arg(ap, SilcInt64);
364 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
365 SILC_PUT64_MSB(x, xf);
366 silc_buffer_put(dst, xf, sizeof(SilcInt64));
367 silc_buffer_pull(dst, sizeof(SilcInt64));
371 case SILC_PARAM_BUFFER:
372 case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
374 SilcBuffer x = va_arg(ap, SilcBuffer);
380 if (x && silc_buffer_len(x)) {
381 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
382 SILC_PUT32_MSB(silc_buffer_len(x), xf);
383 silc_buffer_put(dst, xf, 4);
384 silc_buffer_pull(dst, 4);
385 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
386 silc_buffer_pull(dst, silc_buffer_len(x));
391 case SILC_PARAM_DELETE:
393 int n = va_arg(ap, int);
399 /* Move all data from tail to data area */
400 if (dst->data != dst->tail) {
401 memmove(dst->data, dst->tail, silc_buffer_taillen(dst));
402 memset(dst->end - silc_buffer_len(dst), 0, silc_buffer_len(dst));
403 silc_buffer_push_tail(dst, silc_buffer_len(dst));
408 if (n > silc_buffer_len(dst))
411 memmove(dst->data, dst->data + n, (silc_buffer_len(dst) - n) +
412 silc_buffer_taillen(dst));
413 memset(dst->end - n, 0, n);
414 silc_buffer_push_tail(dst, silc_buffer_len(dst) - n);
419 case SILC_PARAM_OFFSET:
421 int offst = va_arg(ap, int);
430 if (offst > silc_buffer_len(dst)) {
431 silc_set_errno(SILC_ERR_OVERFLOW);
434 silc_buffer_pull(dst, offst);
437 silc_buffer_push(dst, -(offst));
443 case SILC_PARAM_OFFSET_START:
446 if (!silc_buffer_push(dst, flen))
451 case SILC_PARAM_OFFSET_END:
454 flen += silc_buffer_len(dst);
455 silc_buffer_pull(dst, silc_buffer_len(dst));
458 case SILC_PARAM_ADVANCE:
469 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
470 "format the data.", fmt));
471 silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
472 "Bad buffer formatting type %d", fmt);
479 SILC_LOG_DEBUG(("Error occured while formatting data"));
480 if (process && !advance)
481 silc_buffer_push(dst, flen);
485 /* Push the buffer back to where it belongs. */
486 if (process && !advance)
487 silc_buffer_push(dst, flen);
491 int silc_buffer_format(SilcBuffer dst, ...)
497 ret = silc_buffer_sformat_vp(NULL, dst, ap);
503 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
505 return silc_buffer_sformat_vp(NULL, dst, ap);
508 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
514 ret = silc_buffer_sformat_vp(stack, dst, ap);
520 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
522 return silc_buffer_sformat_vp_i(stack, dst, ap, TRUE);
525 /****************************** Unformatting ********************************/
527 int silc_buffer_sunformat_vp_i(SilcStack stack, SilcBuffer src, va_list ap,
531 unsigned char *start_ptr = src->data;
533 SilcBool advance = FALSE;
535 /* Parse the arguments by formatting type. */
537 fmt = va_arg(ap, SilcParam);
539 SILC_LOG_DEBUG(("Buffer unformat type %d", fmt));
542 case SILC_PARAM_FUNC:
544 SilcBufferUnformatFunc func;
548 func = va_arg(ap, SilcBufferUnformatFunc);
549 val = va_arg(ap, void **);
550 context = va_arg(ap, void *);
555 tmp_len = func(stack, src, val, context);
559 UNFORMAT_HAS_SPACE(src, tmp_len);
560 silc_buffer_pull(src, tmp_len);
565 case SILC_PARAM_REGEX:
567 const char *regex = va_arg(ap, char *);
568 SilcBufferRegexFlags rflags = va_arg(ap, SilcUInt32);
569 SilcBufferStruct match;
570 SilcBool match_all = (rflags & SILC_STR_REGEX_ALL) != 0;
571 SilcBool match_nl = (rflags & SILC_STR_REGEX_NL) != 0;
573 SilcUInt32 saved_pos = 0, inclusive_pos = 0;
574 int matched = 0, ret_len;
586 /* Match for '\n' in the buffer. If not found, treat as line
587 without '\n' (buffer has only one line, or this is last line). */
588 saved_pos = silc_buffer_headlen(src) + silc_buffer_len(src);
589 if (silc_regex_buffer(src, "\n", &match, NULL))
590 src->tail = match.tail;
595 ret = silc_regex_buffer(src, regex, &match, NULL);
596 ret ^= (rflags & SILC_STR_REGEX_NOT) != 0;
598 if (!matched && rflags & SILC_STR_REGEX_MISMATCH) {
599 silc_set_errno(SILC_ERR_NOT_FOUND);
606 if (rflags & SILC_STR_REGEX_NOT)
609 if (!(rflags & SILC_STR_REGEX_NO_ADVANCE)) {
610 /* Advance buffer after match */
611 UNFORMAT_HAS_SPACE(src, (match.data - src->data));
612 if (!silc_buffer_pull(src, (match.data - src->data)))
616 if (rflags & SILC_STR_REGEX_INCLUSIVE) {
617 inclusive_pos = src->tail - match.tail;
618 src->tail = match.tail;
621 /* Recursively format */
622 silc_va_copy(cp, ap);
623 ret_len = silc_buffer_sunformat_vp_i(stack, src, cp, TRUE);
628 if (rflags & SILC_STR_REGEX_INCLUSIVE)
629 if (!silc_buffer_pull_tail(src, inclusive_pos))
632 /* Advance buffer after formatting */
633 UNFORMAT_HAS_SPACE(src, ret_len);
634 if (!silc_buffer_pull(src, ret_len))
637 if (match_all && (!match_nl || silc_buffer_len(src) > 1))
642 /* Go to next line, it is at the end of the data area. Adjust
643 the tail area of the target buffer to show rest of the buffer. */
644 UNFORMAT_HAS_SPACE(src, src->tail - src->data);
645 if (!silc_buffer_pull(src, (src->tail - src->data)))
647 if (!silc_buffer_pull_tail(src, (saved_pos -
648 silc_buffer_headlen(src) +
649 silc_buffer_len(src))))
652 if (silc_buffer_len(src) > 0)
656 /* Skip to the next SILC_PARAM_END */
657 silc_buffer_sunformat_vp_i(NULL, src, ap, FALSE);
661 case SILC_PARAM_UICHAR:
663 unsigned char **x = va_arg(ap, unsigned char **);
664 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
669 UNFORMAT_HAS_SPACE(src, len2);
670 if (silc_likely(len2 && x))
672 silc_buffer_pull(src, len2);
676 case SILC_PARAM_UICHAR | SILC_PARAM_ALLOC:
678 unsigned char **x = va_arg(ap, unsigned char **);
679 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
684 UNFORMAT_HAS_SPACE(src, len2);
685 if (silc_likely(len2 && x)) {
686 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
687 memcpy(*x, src->data, len2);
689 silc_buffer_pull(src, len2);
693 case SILC_PARAM_UINT8:
695 unsigned char *x = va_arg(ap, unsigned char *);
700 UNFORMAT_HAS_SPACE(src, 1);
703 silc_buffer_pull(src, 1);
707 case SILC_PARAM_UINT16:
709 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
714 UNFORMAT_HAS_SPACE(src, 2);
716 SILC_GET16_MSB(*x, src->data);
717 silc_buffer_pull(src, 2);
721 case SILC_PARAM_UINT32:
723 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
728 UNFORMAT_HAS_SPACE(src, 4);
730 SILC_GET32_MSB(*x, src->data);
731 silc_buffer_pull(src, 4);
735 case SILC_PARAM_UINT64:
737 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
742 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
744 SILC_GET64_MSB(*x, src->data);
745 silc_buffer_pull(src, sizeof(SilcUInt64));
749 case SILC_PARAM_SINT8:
751 char *x = va_arg(ap, char *);
756 UNFORMAT_HAS_SPACE(src, 1);
759 silc_buffer_pull(src, 1);
763 case SILC_PARAM_SINT16:
765 SilcInt16 *x = va_arg(ap, SilcInt16 *);
770 UNFORMAT_HAS_SPACE(src, 2);
772 SILC_GET16_MSB(*x, src->data);
773 silc_buffer_pull(src, 2);
777 case SILC_PARAM_SINT32:
779 SilcInt32 *x = va_arg(ap, SilcInt32 *);
784 UNFORMAT_HAS_SPACE(src, 4);
786 SILC_GET32_MSB(*x, src->data);
787 silc_buffer_pull(src, 4);
791 case SILC_PARAM_SINT64:
793 SilcInt64 *x = va_arg(ap, SilcInt64 *);
798 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
800 SILC_GET64_MSB(*x, src->data);
801 silc_buffer_pull(src, sizeof(SilcInt64));
805 case SILC_PARAM_UI8_STRING:
808 unsigned char **x = va_arg(ap, unsigned char **);
813 UNFORMAT_HAS_SPACE(src, 1);
814 len2 = (SilcUInt8)src->data[0];
815 silc_buffer_pull(src, 1);
816 UNFORMAT_HAS_SPACE(src, len2);
819 silc_buffer_pull(src, len2);
823 case SILC_PARAM_UI8_STRING | SILC_PARAM_ALLOC:
826 unsigned char **x = va_arg(ap, unsigned char **);
831 UNFORMAT_HAS_SPACE(src, 1);
832 len2 = (SilcUInt8)src->data[0];
833 silc_buffer_pull(src, 1);
834 UNFORMAT_HAS_SPACE(src, len2);
835 if (silc_likely(x && len2)) {
836 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
837 memcpy(*x, src->data, len2);
839 silc_buffer_pull(src, len2);
843 case SILC_PARAM_UI16_STRING:
846 unsigned char **x = va_arg(ap, unsigned char **);
851 UNFORMAT_HAS_SPACE(src, 2);
852 SILC_GET16_MSB(len2, src->data);
853 silc_buffer_pull(src, 2);
854 UNFORMAT_HAS_SPACE(src, len2);
857 silc_buffer_pull(src, len2);
861 case SILC_PARAM_UI16_STRING | SILC_PARAM_ALLOC:
864 unsigned char **x = va_arg(ap, unsigned char **);
869 UNFORMAT_HAS_SPACE(src, 2);
870 SILC_GET16_MSB(len2, src->data);
871 silc_buffer_pull(src, 2);
872 UNFORMAT_HAS_SPACE(src, len2);
873 if (silc_likely(x && len2)) {
874 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
875 memcpy(*x, src->data, len2);
877 silc_buffer_pull(src, len2);
881 case SILC_PARAM_UI32_STRING:
884 unsigned char **x = va_arg(ap, unsigned char **);
889 UNFORMAT_HAS_SPACE(src, 4);
890 SILC_GET32_MSB(len2, src->data);
891 silc_buffer_pull(src, 4);
892 UNFORMAT_HAS_SPACE(src, len2);
895 silc_buffer_pull(src, len2);
899 case SILC_PARAM_UI32_STRING | SILC_PARAM_ALLOC:
902 unsigned char **x = va_arg(ap, unsigned char **);
907 UNFORMAT_HAS_SPACE(src, 4);
908 SILC_GET32_MSB(len2, src->data);
909 silc_buffer_pull(src, 4);
910 UNFORMAT_HAS_SPACE(src, len2);
911 if (silc_likely(x && len2)) {
912 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
913 memcpy(*x, src->data, len2);
915 silc_buffer_pull(src, len2);
919 case SILC_PARAM_UI8_NSTRING:
922 unsigned char **x = va_arg(ap, unsigned char **);
923 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
928 UNFORMAT_HAS_SPACE(src, 1);
929 len2 = (SilcUInt8)src->data[0];
930 silc_buffer_pull(src, 1);
931 UNFORMAT_HAS_SPACE(src, len2);
936 silc_buffer_pull(src, len2);
940 case SILC_PARAM_UI8_NSTRING | SILC_PARAM_ALLOC:
943 unsigned char **x = va_arg(ap, unsigned char **);
944 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
949 UNFORMAT_HAS_SPACE(src, 1);
950 len2 = (SilcUInt8)src->data[0];
951 silc_buffer_pull(src, 1);
952 UNFORMAT_HAS_SPACE(src, len2);
956 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
957 memcpy(*x, src->data, len2);
959 silc_buffer_pull(src, len2);
963 case SILC_PARAM_UI16_NSTRING:
966 unsigned char **x = va_arg(ap, unsigned char **);
967 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
972 UNFORMAT_HAS_SPACE(src, 2);
973 SILC_GET16_MSB(len2, src->data);
974 silc_buffer_pull(src, 2);
975 UNFORMAT_HAS_SPACE(src, len2);
980 silc_buffer_pull(src, len2);
984 case SILC_PARAM_UI16_NSTRING | SILC_PARAM_ALLOC:
987 unsigned char **x = va_arg(ap, unsigned char **);
988 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
993 UNFORMAT_HAS_SPACE(src, 2);
994 SILC_GET16_MSB(len2, src->data);
995 silc_buffer_pull(src, 2);
996 UNFORMAT_HAS_SPACE(src, len2);
1000 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1001 memcpy(*x, src->data, len2);
1003 silc_buffer_pull(src, len2);
1007 case SILC_PARAM_UI32_NSTRING:
1010 unsigned char **x = va_arg(ap, unsigned char **);
1011 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1016 UNFORMAT_HAS_SPACE(src, 4);
1017 SILC_GET32_MSB(len2, src->data);
1018 silc_buffer_pull(src, 4);
1019 UNFORMAT_HAS_SPACE(src, len2);
1024 silc_buffer_pull(src, len2);
1028 case SILC_PARAM_UI32_NSTRING | SILC_PARAM_ALLOC:
1031 unsigned char **x = va_arg(ap, unsigned char **);
1032 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
1037 UNFORMAT_HAS_SPACE(src, 4);
1038 SILC_GET32_MSB(len2, src->data);
1039 silc_buffer_pull(src, 4);
1040 UNFORMAT_HAS_SPACE(src, len2);
1043 if (silc_likely(x && len2)) {
1044 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
1045 memcpy(*x, src->data, len2);
1047 silc_buffer_pull(src, len2);
1051 case SILC_PARAM_BUFFER:
1053 SilcBuffer x = va_arg(ap, SilcBuffer);
1059 UNFORMAT_HAS_SPACE(src, 4);
1060 SILC_GET32_MSB(len2, src->data);
1061 silc_buffer_pull(src, 4);
1062 UNFORMAT_HAS_SPACE(src, len2);
1063 silc_buffer_set(x, src->data, len2);
1064 silc_buffer_pull(src, len2);
1068 case SILC_PARAM_BUFFER | SILC_PARAM_ALLOC:
1070 SilcBuffer x = va_arg(ap, SilcBuffer);
1076 UNFORMAT_HAS_SPACE(src, 4);
1077 SILC_GET32_MSB(len2, src->data);
1078 silc_buffer_pull(src, 4);
1079 UNFORMAT_HAS_SPACE(src, len2);
1080 silc_buffer_sformat(stack, x,
1081 SILC_STR_DATA(src->data, len2),
1083 silc_buffer_pull(src, len2);
1087 case SILC_PARAM_OFFSET:
1089 int offst = va_arg(ap, int);
1098 UNFORMAT_HAS_SPACE(src, offst);
1099 silc_buffer_pull(src, offst);
1101 silc_buffer_push(src, -(offst));
1106 case SILC_PARAM_OFFSET_START:
1109 silc_buffer_push(src, (src->data - start_ptr));
1112 case SILC_PARAM_OFFSET_END:
1115 silc_buffer_pull(src, silc_buffer_len(src));
1118 case SILC_PARAM_ADVANCE:
1124 case SILC_PARAM_END:
1128 case SILC_PARAM_DELETE:
1132 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
1133 "format the data.", fmt));
1134 silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
1135 "Bad buffer formatting type %d", fmt);
1142 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
1143 if (process && !advance) {
1144 len = src->data - start_ptr;
1145 silc_buffer_push(src, len);
1150 /* Push the buffer back to the start. */
1151 if (process && !advance) {
1152 len = src->data - start_ptr;
1153 silc_buffer_push(src, len);
1158 int silc_buffer_unformat(SilcBuffer src, ...)
1164 ret = silc_buffer_sunformat_vp(NULL, src, ap);
1170 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
1172 return silc_buffer_sunformat_vp(NULL, src, ap);
1175 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
1181 ret = silc_buffer_sunformat_vp(stack, src, ap);
1187 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
1189 return silc_buffer_sunformat_vp_i(stack, src, ap, TRUE);
1192 /**************************** Utility functions *****************************/
1194 /* Formats strings into a buffer */
1196 int silc_buffer_strformat(SilcBuffer dst, ...)
1198 int len = silc_buffer_truelen(dst);
1199 int hlen = silc_buffer_headlen(dst);
1204 /* Parse the arguments by formatting type. */
1206 char *string = va_arg(va, char *);
1212 if (string == (char *)SILC_PARAM_END)
1215 slen = strlen(string);
1216 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
1217 if (silc_unlikely(!d))
1220 memcpy(dst->head + len, string, slen);
1222 dst->head[len] = '\0';
1225 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
1230 dst->end = dst->head + len;
1231 dst->data = dst->head + hlen;
1232 dst->tail = dst->end;
1238 /* Formats strings into a buffer. Allocates memory from SilcStack. */
1240 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
1242 int len = silc_buffer_truelen(dst);
1243 int hlen = silc_buffer_headlen(dst);
1248 /* Parse the arguments by formatting type. */
1250 char *string = va_arg(va, char *);
1256 if (string == (char *)SILC_PARAM_END)
1259 slen = strlen(string);
1260 d = silc_srealloc(stack, len + 1, dst->head,
1261 sizeof(*dst->head) * (slen + len + 1));
1262 if (silc_unlikely(!d))
1265 memcpy(dst->head + len, string, slen);
1267 dst->head[len] = '\0';
1270 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
1275 dst->end = dst->head + len;
1276 dst->data = dst->head + hlen;
1277 dst->tail = dst->end;