5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
23 /************************** Types and definitions ***************************/
25 /* Check that buffer has enough room to format data in it, if not
27 #define FORMAT_HAS_SPACE(s, b, req) \
29 if (silc_unlikely(!silc_buffer_senlarge(s, b, req))) \
34 /* Check that there is data to be unformatted */
35 #define UNFORMAT_HAS_SPACE(b, req) \
37 if (silc_unlikely(req > silc_buffer_len(b))) \
39 if (silc_unlikely((req + 1) <= 0)) \
44 /******************************* Formatting *********************************/
46 int silc_buffer_format(SilcBuffer dst, ...)
52 ret = silc_buffer_sformat_vp(NULL, dst, ap);
58 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
60 return silc_buffer_sformat_vp(NULL, dst, ap);
63 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
69 ret = silc_buffer_sformat_vp(stack, dst, ap);
75 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
77 SilcBufferParamType fmt;
79 SilcBool advance = FALSE;
81 /* Parse the arguments by formatting type. */
83 fmt = va_arg(ap, SilcBufferParamType);
88 SilcBufferFormatFunc func = NULL;
89 SilcBufferSFormatFunc funcs = NULL;
94 func = va_arg(ap, SilcBufferFormatFunc);
96 funcs = va_arg(ap, SilcBufferSFormatFunc);
97 val = va_arg(ap, void *);
98 context = va_arg(ap, void *);
100 tmp_len = func(dst, val, context);
102 tmp_len = funcs(stack, dst, val, context);
106 silc_buffer_pull(dst, tmp_len);
111 case SILC_PARAM_UI8_STRING:
112 case SILC_PARAM_UI16_STRING:
113 case SILC_PARAM_UI32_STRING:
114 case SILC_PARAM_UI8_STRING_ALLOC:
115 case SILC_PARAM_UI16_STRING_ALLOC:
116 case SILC_PARAM_UI32_STRING_ALLOC:
118 unsigned char *x = va_arg(ap, unsigned char *);
119 SilcUInt32 tmp_len = x ? strlen(x) : 0;
121 FORMAT_HAS_SPACE(stack, dst, tmp_len);
122 silc_buffer_put(dst, x, tmp_len);
123 silc_buffer_pull(dst, tmp_len);
127 case SILC_PARAM_UI8_NSTRING:
128 case SILC_PARAM_UI16_NSTRING:
129 case SILC_PARAM_UI32_NSTRING:
130 case SILC_PARAM_UI_XNSTRING:
131 case SILC_PARAM_DATA:
132 case SILC_PARAM_UI8_NSTRING_ALLOC:
133 case SILC_PARAM_UI16_NSTRING_ALLOC:
134 case SILC_PARAM_UI32_NSTRING_ALLOC:
135 case SILC_PARAM_UI_XNSTRING_ALLOC:
136 case SILC_PARAM_DATA_ALLOC:
138 unsigned char *x = va_arg(ap, unsigned char *);
139 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
141 FORMAT_HAS_SPACE(stack, dst, tmp_len);
142 silc_buffer_put(dst, x, tmp_len);
143 silc_buffer_pull(dst, tmp_len);
147 case SILC_PARAM_UI8_CHAR:
149 unsigned char x = (unsigned char)va_arg(ap, int);
150 FORMAT_HAS_SPACE(stack, dst, 1);
151 silc_buffer_put(dst, &x, 1);
152 silc_buffer_pull(dst, 1);
155 case SILC_PARAM_UI16_SHORT:
158 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
159 FORMAT_HAS_SPACE(stack, dst, 2);
160 SILC_PUT16_MSB(x, xf);
161 silc_buffer_put(dst, xf, 2);
162 silc_buffer_pull(dst, 2);
165 case SILC_PARAM_UI32_INT:
168 SilcUInt32 x = va_arg(ap, SilcUInt32);
169 FORMAT_HAS_SPACE(stack, dst, 4);
170 SILC_PUT32_MSB(x, xf);
171 silc_buffer_put(dst, xf, 4);
172 silc_buffer_pull(dst, 4);
175 case SILC_PARAM_UI64_INT:
178 SilcUInt64 x = va_arg(ap, SilcUInt64);
179 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
180 SILC_PUT64_MSB(x, xf);
181 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
182 silc_buffer_pull(dst, sizeof(SilcUInt64));
185 case SILC_PARAM_SI8_CHAR:
187 char x = (char)va_arg(ap, int);
188 FORMAT_HAS_SPACE(stack, dst, 1);
189 silc_buffer_put(dst, &x, 1);
190 silc_buffer_pull(dst, 1);
193 case SILC_PARAM_SI16_SHORT:
196 SilcInt16 x = (SilcInt16)va_arg(ap, int);
197 FORMAT_HAS_SPACE(stack, dst, 2);
198 SILC_PUT16_MSB(x, xf);
199 silc_buffer_put(dst, xf, 2);
200 silc_buffer_pull(dst, 2);
203 case SILC_PARAM_SI32_INT:
206 SilcInt32 x = va_arg(ap, SilcInt32);
207 FORMAT_HAS_SPACE(stack, dst, 4);
208 SILC_PUT32_MSB(x, xf);
209 silc_buffer_put(dst, xf, 4);
210 silc_buffer_pull(dst, 4);
213 case SILC_PARAM_SI64_INT:
216 SilcInt64 x = va_arg(ap, SilcInt64);
217 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
218 SILC_PUT64_MSB(x, xf);
219 silc_buffer_put(dst, xf, sizeof(SilcInt64));
220 silc_buffer_pull(dst, sizeof(SilcInt64));
223 case SILC_PARAM_BUFFER:
224 case SILC_PARAM_BUFFER_ALLOC:
226 SilcBuffer x = va_arg(ap, SilcBuffer);
228 if (x && silc_buffer_len(x)) {
229 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
230 SILC_PUT32_MSB(silc_buffer_len(x), xf);
231 silc_buffer_put(dst, xf, 4);
232 silc_buffer_pull(dst, 4);
233 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
234 silc_buffer_pull(dst, silc_buffer_len(x));
238 case SILC_PARAM_OFFSET:
240 int offst = va_arg(ap, int);
244 if (offst > silc_buffer_len(dst))
246 silc_buffer_pull(dst, offst);
249 silc_buffer_push(dst, -(offst));
254 case SILC_PARAM_ADVANCE:
261 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
262 "format the data.", fmt));
269 SILC_LOG_DEBUG(("Error occured while formatting data"));
271 silc_buffer_push(dst, flen);
275 /* Push the buffer back to where it belongs. */
277 silc_buffer_push(dst, flen);
282 /****************************** Unformatting ********************************/
284 int silc_buffer_unformat(SilcBuffer src, ...)
290 ret = silc_buffer_sunformat_vp(NULL, src, ap);
296 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
298 return silc_buffer_sunformat_vp(NULL, src, ap);
301 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
307 ret = silc_buffer_sunformat_vp(stack, src, ap);
313 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
315 SilcBufferParamType fmt;
316 unsigned char *start_ptr = src->data;
318 SilcBool advance = FALSE;
320 /* Parse the arguments by formatting type. */
322 fmt = va_arg(ap, SilcBufferParamType);
325 case SILC_PARAM_FUNC:
327 SilcBufferUnformatFunc func = NULL;
328 SilcBufferSUnformatFunc funcs = NULL;
333 func = va_arg(ap, SilcBufferUnformatFunc);
335 funcs = va_arg(ap, SilcBufferSUnformatFunc);
336 val = va_arg(ap, void **);
337 context = va_arg(ap, void *);
339 tmp_len = func(src, val, context);
341 tmp_len = funcs(stack, src, val, context);
345 UNFORMAT_HAS_SPACE(src, tmp_len);
346 silc_buffer_pull(src, tmp_len);
349 case SILC_PARAM_UI_XNSTRING:
350 case SILC_PARAM_DATA:
352 unsigned char **x = va_arg(ap, unsigned char **);
353 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
354 UNFORMAT_HAS_SPACE(src, len2);
355 if (silc_likely(len2 && x))
357 silc_buffer_pull(src, len2);
360 case SILC_PARAM_UI_XNSTRING_ALLOC:
361 case SILC_PARAM_DATA_ALLOC:
363 unsigned char **x = va_arg(ap, unsigned char **);
364 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
365 UNFORMAT_HAS_SPACE(src, len2);
366 if (silc_likely(len2 && x)) {
367 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
369 memcpy(*x, src->data, len2);
371 silc_buffer_pull(src, len2);
374 case SILC_PARAM_UI8_CHAR:
376 unsigned char *x = va_arg(ap, unsigned char *);
377 UNFORMAT_HAS_SPACE(src, 1);
380 silc_buffer_pull(src, 1);
383 case SILC_PARAM_UI16_SHORT:
385 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
386 UNFORMAT_HAS_SPACE(src, 2);
388 SILC_GET16_MSB(*x, src->data);
389 silc_buffer_pull(src, 2);
392 case SILC_PARAM_UI32_INT:
394 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
395 UNFORMAT_HAS_SPACE(src, 4);
397 SILC_GET32_MSB(*x, src->data);
398 silc_buffer_pull(src, 4);
401 case SILC_PARAM_UI64_INT:
403 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
404 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
406 SILC_GET64_MSB(*x, src->data);
407 silc_buffer_pull(src, sizeof(SilcUInt64));
410 case SILC_PARAM_SI8_CHAR:
412 char *x = va_arg(ap, char *);
413 UNFORMAT_HAS_SPACE(src, 1);
416 silc_buffer_pull(src, 1);
419 case SILC_PARAM_SI16_SHORT:
421 SilcInt16 *x = va_arg(ap, SilcInt16 *);
422 UNFORMAT_HAS_SPACE(src, 2);
424 SILC_GET16_MSB(*x, src->data);
425 silc_buffer_pull(src, 2);
428 case SILC_PARAM_SI32_INT:
430 SilcInt32 *x = va_arg(ap, SilcInt32 *);
431 UNFORMAT_HAS_SPACE(src, 4);
433 SILC_GET32_MSB(*x, src->data);
434 silc_buffer_pull(src, 4);
437 case SILC_PARAM_SI64_INT:
439 SilcInt64 *x = va_arg(ap, SilcInt64 *);
440 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
442 SILC_GET64_MSB(*x, src->data);
443 silc_buffer_pull(src, sizeof(SilcInt64));
446 case SILC_PARAM_UI8_STRING:
449 unsigned char **x = va_arg(ap, unsigned char **);
450 UNFORMAT_HAS_SPACE(src, 1);
451 len2 = (SilcUInt8)src->data[0];
452 silc_buffer_pull(src, 1);
453 UNFORMAT_HAS_SPACE(src, len2);
456 silc_buffer_pull(src, len2);
459 case SILC_PARAM_UI16_STRING:
462 unsigned char **x = va_arg(ap, unsigned char **);
463 UNFORMAT_HAS_SPACE(src, 2);
464 SILC_GET16_MSB(len2, src->data);
465 silc_buffer_pull(src, 2);
466 UNFORMAT_HAS_SPACE(src, len2);
469 silc_buffer_pull(src, len2);
472 case SILC_PARAM_UI8_STRING_ALLOC:
475 unsigned char **x = va_arg(ap, unsigned char **);
476 UNFORMAT_HAS_SPACE(src, 1);
477 len2 = (SilcUInt8)src->data[0];
478 silc_buffer_pull(src, 1);
479 UNFORMAT_HAS_SPACE(src, len2);
480 if (silc_likely(x && len2)) {
481 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
483 memcpy(*x, src->data, len2);
485 silc_buffer_pull(src, len2);
488 case SILC_PARAM_UI16_STRING_ALLOC:
491 unsigned char **x = va_arg(ap, unsigned char **);
492 UNFORMAT_HAS_SPACE(src, 2);
493 SILC_GET16_MSB(len2, src->data);
494 silc_buffer_pull(src, 2);
495 UNFORMAT_HAS_SPACE(src, len2);
496 if (silc_likely(x && len2)) {
497 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
499 memcpy(*x, src->data, len2);
501 silc_buffer_pull(src, len2);
504 case SILC_PARAM_UI32_STRING:
507 unsigned char **x = va_arg(ap, unsigned char **);
508 UNFORMAT_HAS_SPACE(src, 4);
509 SILC_GET32_MSB(len2, src->data);
510 silc_buffer_pull(src, 4);
511 UNFORMAT_HAS_SPACE(src, len2);
514 silc_buffer_pull(src, len2);
517 case SILC_PARAM_UI32_STRING_ALLOC:
520 unsigned char **x = va_arg(ap, unsigned char **);
521 UNFORMAT_HAS_SPACE(src, 4);
522 SILC_GET32_MSB(len2, src->data);
523 silc_buffer_pull(src, 4);
524 UNFORMAT_HAS_SPACE(src, len2);
525 if (silc_likely(x && len2)) {
526 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
528 memcpy(*x, src->data, len2);
530 silc_buffer_pull(src, len2);
533 case SILC_PARAM_UI8_NSTRING:
536 unsigned char **x = va_arg(ap, unsigned char **);
537 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
538 UNFORMAT_HAS_SPACE(src, 1);
539 len2 = (SilcUInt8)src->data[0];
540 silc_buffer_pull(src, 1);
541 UNFORMAT_HAS_SPACE(src, len2);
546 silc_buffer_pull(src, len2);
549 case SILC_PARAM_UI16_NSTRING:
552 unsigned char **x = va_arg(ap, unsigned char **);
553 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
554 UNFORMAT_HAS_SPACE(src, 2);
555 SILC_GET16_MSB(len2, src->data);
556 silc_buffer_pull(src, 2);
557 UNFORMAT_HAS_SPACE(src, len2);
562 silc_buffer_pull(src, len2);
565 case SILC_PARAM_UI8_NSTRING_ALLOC:
568 unsigned char **x = va_arg(ap, unsigned char **);
569 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
570 UNFORMAT_HAS_SPACE(src, 1);
571 len2 = (SilcUInt8)src->data[0];
572 silc_buffer_pull(src, 1);
573 UNFORMAT_HAS_SPACE(src, len2);
577 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
579 memcpy(*x, src->data, len2);
581 silc_buffer_pull(src, len2);
584 case SILC_PARAM_UI16_NSTRING_ALLOC:
587 unsigned char **x = va_arg(ap, unsigned char **);
588 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
589 UNFORMAT_HAS_SPACE(src, 2);
590 SILC_GET16_MSB(len2, src->data);
591 silc_buffer_pull(src, 2);
592 UNFORMAT_HAS_SPACE(src, len2);
596 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
598 memcpy(*x, src->data, len2);
600 silc_buffer_pull(src, len2);
603 case SILC_PARAM_UI32_NSTRING:
606 unsigned char **x = va_arg(ap, unsigned char **);
607 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
608 UNFORMAT_HAS_SPACE(src, 4);
609 SILC_GET32_MSB(len2, src->data);
610 silc_buffer_pull(src, 4);
611 UNFORMAT_HAS_SPACE(src, len2);
616 silc_buffer_pull(src, len2);
619 case SILC_PARAM_BUFFER:
621 SilcBuffer x = va_arg(ap, SilcBuffer);
623 UNFORMAT_HAS_SPACE(src, 4);
624 SILC_GET32_MSB(len2, src->data);
625 silc_buffer_pull(src, 4);
626 UNFORMAT_HAS_SPACE(src, len2);
627 silc_buffer_set(x, src->data, len2);
628 silc_buffer_pull(src, len2);
631 case SILC_PARAM_BUFFER_ALLOC:
633 SilcBuffer x = va_arg(ap, SilcBuffer);
635 UNFORMAT_HAS_SPACE(src, 4);
636 SILC_GET32_MSB(len2, src->data);
637 silc_buffer_pull(src, 4);
638 UNFORMAT_HAS_SPACE(src, len2);
639 if (silc_buffer_sformat(stack, x,
640 SILC_STR_DATA(src->data, len2),
643 silc_buffer_pull(src, len2);
646 case SILC_PARAM_OFFSET:
648 int offst = va_arg(ap, int);
652 UNFORMAT_HAS_SPACE(src, offst);
653 silc_buffer_pull(src, offst);
655 silc_buffer_push(src, -(offst));
659 case SILC_PARAM_ADVANCE:
666 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
667 "format the data.", fmt));
674 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
675 len = src->data - start_ptr;
676 silc_buffer_push(src, len);
680 /* Push the buffer back to the start. */
682 len = src->data - start_ptr;
683 silc_buffer_push(src, len);
689 /**************************** Utility functions *****************************/
691 /* Formats strings into a buffer */
693 int silc_buffer_strformat(SilcBuffer dst, ...)
695 int len = silc_buffer_truelen(dst);
696 int hlen = silc_buffer_headlen(dst);
701 /* Parse the arguments by formatting type. */
703 char *string = va_arg(va, char *);
709 if (string == (char *)SILC_PARAM_END)
712 slen = strlen(string);
713 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
714 if (silc_unlikely(!d))
717 memcpy(dst->head + len, string, slen);
719 dst->head[len] = '\0';
722 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
727 dst->end = dst->head + len;
728 dst->data = dst->head + hlen;
729 dst->tail = dst->end;
735 /* Formats strings into a buffer. Allocates memory from SilcStack. */
737 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
739 int len = silc_buffer_truelen(dst);
740 int hlen = silc_buffer_headlen(dst);
745 /* Parse the arguments by formatting type. */
747 char *string = va_arg(va, char *);
753 if (string == (char *)SILC_PARAM_END)
756 slen = strlen(string);
757 d = silc_srealloc(stack, len + 1, dst->head,
758 sizeof(*dst->head) * (slen + len + 1));
759 if (silc_unlikely(!d))
762 memcpy(dst->head + len, string, slen);
764 dst->head[len] = '\0';
767 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
772 dst->end = dst->head + len;
773 dst->data = dst->head + hlen;
774 dst->tail = dst->end;