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;
92 func = va_arg(ap, SilcBufferFormatFunc);
93 val = va_arg(ap, void *);
94 context = va_arg(ap, void *);
95 tmp_len = func(stack, dst, val, context);
99 silc_buffer_pull(dst, tmp_len);
104 case SILC_PARAM_UI8_STRING:
105 case SILC_PARAM_UI16_STRING:
106 case SILC_PARAM_UI32_STRING:
107 case SILC_PARAM_UI8_STRING_ALLOC:
108 case SILC_PARAM_UI16_STRING_ALLOC:
109 case SILC_PARAM_UI32_STRING_ALLOC:
111 unsigned char *x = va_arg(ap, unsigned char *);
112 SilcUInt32 tmp_len = x ? strlen(x) : 0;
114 FORMAT_HAS_SPACE(stack, dst, tmp_len);
115 silc_buffer_put(dst, x, tmp_len);
116 silc_buffer_pull(dst, tmp_len);
120 case SILC_PARAM_UI8_NSTRING:
121 case SILC_PARAM_UI16_NSTRING:
122 case SILC_PARAM_UI32_NSTRING:
123 case SILC_PARAM_UI_XNSTRING:
124 case SILC_PARAM_DATA:
125 case SILC_PARAM_UI8_NSTRING_ALLOC:
126 case SILC_PARAM_UI16_NSTRING_ALLOC:
127 case SILC_PARAM_UI32_NSTRING_ALLOC:
128 case SILC_PARAM_UI_XNSTRING_ALLOC:
129 case SILC_PARAM_DATA_ALLOC:
131 unsigned char *x = va_arg(ap, unsigned char *);
132 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
134 FORMAT_HAS_SPACE(stack, dst, tmp_len);
135 silc_buffer_put(dst, x, tmp_len);
136 silc_buffer_pull(dst, tmp_len);
140 case SILC_PARAM_UI8_CHAR:
142 unsigned char x = (unsigned char)va_arg(ap, int);
143 FORMAT_HAS_SPACE(stack, dst, 1);
144 silc_buffer_put(dst, &x, 1);
145 silc_buffer_pull(dst, 1);
148 case SILC_PARAM_UI16_SHORT:
151 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
152 FORMAT_HAS_SPACE(stack, dst, 2);
153 SILC_PUT16_MSB(x, xf);
154 silc_buffer_put(dst, xf, 2);
155 silc_buffer_pull(dst, 2);
158 case SILC_PARAM_UI32_INT:
161 SilcUInt32 x = va_arg(ap, SilcUInt32);
162 FORMAT_HAS_SPACE(stack, dst, 4);
163 SILC_PUT32_MSB(x, xf);
164 silc_buffer_put(dst, xf, 4);
165 silc_buffer_pull(dst, 4);
168 case SILC_PARAM_UI64_INT:
171 SilcUInt64 x = va_arg(ap, SilcUInt64);
172 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
173 SILC_PUT64_MSB(x, xf);
174 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
175 silc_buffer_pull(dst, sizeof(SilcUInt64));
178 case SILC_PARAM_SI8_CHAR:
180 char x = (char)va_arg(ap, int);
181 FORMAT_HAS_SPACE(stack, dst, 1);
182 silc_buffer_put(dst, &x, 1);
183 silc_buffer_pull(dst, 1);
186 case SILC_PARAM_SI16_SHORT:
189 SilcInt16 x = (SilcInt16)va_arg(ap, int);
190 FORMAT_HAS_SPACE(stack, dst, 2);
191 SILC_PUT16_MSB(x, xf);
192 silc_buffer_put(dst, xf, 2);
193 silc_buffer_pull(dst, 2);
196 case SILC_PARAM_SI32_INT:
199 SilcInt32 x = va_arg(ap, SilcInt32);
200 FORMAT_HAS_SPACE(stack, dst, 4);
201 SILC_PUT32_MSB(x, xf);
202 silc_buffer_put(dst, xf, 4);
203 silc_buffer_pull(dst, 4);
206 case SILC_PARAM_SI64_INT:
209 SilcInt64 x = va_arg(ap, SilcInt64);
210 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
211 SILC_PUT64_MSB(x, xf);
212 silc_buffer_put(dst, xf, sizeof(SilcInt64));
213 silc_buffer_pull(dst, sizeof(SilcInt64));
216 case SILC_PARAM_BUFFER:
217 case SILC_PARAM_BUFFER_ALLOC:
219 SilcBuffer x = va_arg(ap, SilcBuffer);
221 if (x && silc_buffer_len(x)) {
222 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
223 SILC_PUT32_MSB(silc_buffer_len(x), xf);
224 silc_buffer_put(dst, xf, 4);
225 silc_buffer_pull(dst, 4);
226 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
227 silc_buffer_pull(dst, silc_buffer_len(x));
231 case SILC_PARAM_OFFSET:
233 int offst = va_arg(ap, int);
237 if (offst > silc_buffer_len(dst))
239 silc_buffer_pull(dst, offst);
242 silc_buffer_push(dst, -(offst));
247 case SILC_PARAM_ADVANCE:
254 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
255 "format the data.", fmt));
262 SILC_LOG_DEBUG(("Error occured while formatting data"));
264 silc_buffer_push(dst, flen);
268 /* Push the buffer back to where it belongs. */
270 silc_buffer_push(dst, flen);
275 /****************************** Unformatting ********************************/
277 int silc_buffer_unformat(SilcBuffer src, ...)
283 ret = silc_buffer_sunformat_vp(NULL, src, ap);
289 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
291 return silc_buffer_sunformat_vp(NULL, src, ap);
294 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
300 ret = silc_buffer_sunformat_vp(stack, src, ap);
306 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
308 SilcBufferParamType fmt;
309 unsigned char *start_ptr = src->data;
311 SilcBool advance = FALSE;
313 /* Parse the arguments by formatting type. */
315 fmt = va_arg(ap, SilcBufferParamType);
318 case SILC_PARAM_FUNC:
320 SilcBufferUnformatFunc func;
324 func = va_arg(ap, SilcBufferUnformatFunc);
325 val = va_arg(ap, void **);
326 context = va_arg(ap, void *);
327 tmp_len = func(stack, src, val, context);
331 UNFORMAT_HAS_SPACE(src, tmp_len);
332 silc_buffer_pull(src, tmp_len);
335 case SILC_PARAM_UI_XNSTRING:
336 case SILC_PARAM_DATA:
338 unsigned char **x = va_arg(ap, unsigned char **);
339 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
340 UNFORMAT_HAS_SPACE(src, len2);
341 if (silc_likely(len2 && x))
343 silc_buffer_pull(src, len2);
346 case SILC_PARAM_UI_XNSTRING_ALLOC:
347 case SILC_PARAM_DATA_ALLOC:
349 unsigned char **x = va_arg(ap, unsigned char **);
350 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
351 UNFORMAT_HAS_SPACE(src, len2);
352 if (silc_likely(len2 && x)) {
353 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
354 memcpy(*x, src->data, len2);
356 silc_buffer_pull(src, len2);
359 case SILC_PARAM_UI8_CHAR:
361 unsigned char *x = va_arg(ap, unsigned char *);
362 UNFORMAT_HAS_SPACE(src, 1);
365 silc_buffer_pull(src, 1);
368 case SILC_PARAM_UI16_SHORT:
370 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
371 UNFORMAT_HAS_SPACE(src, 2);
373 SILC_GET16_MSB(*x, src->data);
374 silc_buffer_pull(src, 2);
377 case SILC_PARAM_UI32_INT:
379 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
380 UNFORMAT_HAS_SPACE(src, 4);
382 SILC_GET32_MSB(*x, src->data);
383 silc_buffer_pull(src, 4);
386 case SILC_PARAM_UI64_INT:
388 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
389 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
391 SILC_GET64_MSB(*x, src->data);
392 silc_buffer_pull(src, sizeof(SilcUInt64));
395 case SILC_PARAM_SI8_CHAR:
397 char *x = va_arg(ap, char *);
398 UNFORMAT_HAS_SPACE(src, 1);
401 silc_buffer_pull(src, 1);
404 case SILC_PARAM_SI16_SHORT:
406 SilcInt16 *x = va_arg(ap, SilcInt16 *);
407 UNFORMAT_HAS_SPACE(src, 2);
409 SILC_GET16_MSB(*x, src->data);
410 silc_buffer_pull(src, 2);
413 case SILC_PARAM_SI32_INT:
415 SilcInt32 *x = va_arg(ap, SilcInt32 *);
416 UNFORMAT_HAS_SPACE(src, 4);
418 SILC_GET32_MSB(*x, src->data);
419 silc_buffer_pull(src, 4);
422 case SILC_PARAM_SI64_INT:
424 SilcInt64 *x = va_arg(ap, SilcInt64 *);
425 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
427 SILC_GET64_MSB(*x, src->data);
428 silc_buffer_pull(src, sizeof(SilcInt64));
431 case SILC_PARAM_UI8_STRING:
434 unsigned char **x = va_arg(ap, unsigned char **);
435 UNFORMAT_HAS_SPACE(src, 1);
436 len2 = (SilcUInt8)src->data[0];
437 silc_buffer_pull(src, 1);
438 UNFORMAT_HAS_SPACE(src, len2);
441 silc_buffer_pull(src, len2);
444 case SILC_PARAM_UI16_STRING:
447 unsigned char **x = va_arg(ap, unsigned char **);
448 UNFORMAT_HAS_SPACE(src, 2);
449 SILC_GET16_MSB(len2, src->data);
450 silc_buffer_pull(src, 2);
451 UNFORMAT_HAS_SPACE(src, len2);
454 silc_buffer_pull(src, len2);
457 case SILC_PARAM_UI8_STRING_ALLOC:
460 unsigned char **x = va_arg(ap, unsigned char **);
461 UNFORMAT_HAS_SPACE(src, 1);
462 len2 = (SilcUInt8)src->data[0];
463 silc_buffer_pull(src, 1);
464 UNFORMAT_HAS_SPACE(src, len2);
465 if (silc_likely(x && len2)) {
466 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
467 memcpy(*x, src->data, len2);
469 silc_buffer_pull(src, len2);
472 case SILC_PARAM_UI16_STRING_ALLOC:
475 unsigned char **x = va_arg(ap, unsigned char **);
476 UNFORMAT_HAS_SPACE(src, 2);
477 SILC_GET16_MSB(len2, src->data);
478 silc_buffer_pull(src, 2);
479 UNFORMAT_HAS_SPACE(src, len2);
480 if (silc_likely(x && len2)) {
481 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
482 memcpy(*x, src->data, len2);
484 silc_buffer_pull(src, len2);
487 case SILC_PARAM_UI32_STRING:
490 unsigned char **x = va_arg(ap, unsigned char **);
491 UNFORMAT_HAS_SPACE(src, 4);
492 SILC_GET32_MSB(len2, src->data);
493 silc_buffer_pull(src, 4);
494 UNFORMAT_HAS_SPACE(src, len2);
497 silc_buffer_pull(src, len2);
500 case SILC_PARAM_UI32_STRING_ALLOC:
503 unsigned char **x = va_arg(ap, unsigned char **);
504 UNFORMAT_HAS_SPACE(src, 4);
505 SILC_GET32_MSB(len2, src->data);
506 silc_buffer_pull(src, 4);
507 UNFORMAT_HAS_SPACE(src, len2);
508 if (silc_likely(x && len2)) {
509 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
510 memcpy(*x, src->data, len2);
512 silc_buffer_pull(src, len2);
515 case SILC_PARAM_UI8_NSTRING:
518 unsigned char **x = va_arg(ap, unsigned char **);
519 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
520 UNFORMAT_HAS_SPACE(src, 1);
521 len2 = (SilcUInt8)src->data[0];
522 silc_buffer_pull(src, 1);
523 UNFORMAT_HAS_SPACE(src, len2);
528 silc_buffer_pull(src, len2);
531 case SILC_PARAM_UI16_NSTRING:
534 unsigned char **x = va_arg(ap, unsigned char **);
535 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
536 UNFORMAT_HAS_SPACE(src, 2);
537 SILC_GET16_MSB(len2, src->data);
538 silc_buffer_pull(src, 2);
539 UNFORMAT_HAS_SPACE(src, len2);
544 silc_buffer_pull(src, len2);
547 case SILC_PARAM_UI8_NSTRING_ALLOC:
550 unsigned char **x = va_arg(ap, unsigned char **);
551 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
552 UNFORMAT_HAS_SPACE(src, 1);
553 len2 = (SilcUInt8)src->data[0];
554 silc_buffer_pull(src, 1);
555 UNFORMAT_HAS_SPACE(src, len2);
559 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
560 memcpy(*x, src->data, len2);
562 silc_buffer_pull(src, len2);
565 case SILC_PARAM_UI16_NSTRING_ALLOC:
568 unsigned char **x = va_arg(ap, unsigned char **);
569 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
570 UNFORMAT_HAS_SPACE(src, 2);
571 SILC_GET16_MSB(len2, src->data);
572 silc_buffer_pull(src, 2);
573 UNFORMAT_HAS_SPACE(src, len2);
577 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
578 memcpy(*x, src->data, len2);
580 silc_buffer_pull(src, len2);
583 case SILC_PARAM_UI32_NSTRING:
586 unsigned char **x = va_arg(ap, unsigned char **);
587 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
588 UNFORMAT_HAS_SPACE(src, 4);
589 SILC_GET32_MSB(len2, src->data);
590 silc_buffer_pull(src, 4);
591 UNFORMAT_HAS_SPACE(src, len2);
596 silc_buffer_pull(src, len2);
599 case SILC_PARAM_BUFFER:
601 SilcBuffer x = va_arg(ap, SilcBuffer);
603 UNFORMAT_HAS_SPACE(src, 4);
604 SILC_GET32_MSB(len2, src->data);
605 silc_buffer_pull(src, 4);
606 UNFORMAT_HAS_SPACE(src, len2);
607 silc_buffer_set(x, src->data, len2);
608 silc_buffer_pull(src, len2);
611 case SILC_PARAM_BUFFER_ALLOC:
613 SilcBuffer x = va_arg(ap, SilcBuffer);
615 UNFORMAT_HAS_SPACE(src, 4);
616 SILC_GET32_MSB(len2, src->data);
617 silc_buffer_pull(src, 4);
618 UNFORMAT_HAS_SPACE(src, len2);
619 silc_buffer_sformat(stack, x,
620 SILC_STR_DATA(src->data, len2),
622 silc_buffer_pull(src, len2);
625 case SILC_PARAM_OFFSET:
627 int offst = va_arg(ap, int);
631 UNFORMAT_HAS_SPACE(src, offst);
632 silc_buffer_pull(src, offst);
634 silc_buffer_push(src, -(offst));
638 case SILC_PARAM_ADVANCE:
645 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
646 "format the data.", fmt));
653 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
654 len = src->data - start_ptr;
655 silc_buffer_push(src, len);
659 /* Push the buffer back to the start. */
661 len = src->data - start_ptr;
662 silc_buffer_push(src, len);
668 /**************************** Utility functions *****************************/
670 /* Formats strings into a buffer */
672 int silc_buffer_strformat(SilcBuffer dst, ...)
674 int len = silc_buffer_truelen(dst);
675 int hlen = silc_buffer_headlen(dst);
680 /* Parse the arguments by formatting type. */
682 char *string = va_arg(va, char *);
688 if (string == (char *)SILC_PARAM_END)
691 slen = strlen(string);
692 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
693 if (silc_unlikely(!d))
696 memcpy(dst->head + len, string, slen);
698 dst->head[len] = '\0';
701 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
706 dst->end = dst->head + len;
707 dst->data = dst->head + hlen;
708 dst->tail = dst->end;
714 /* Formats strings into a buffer. Allocates memory from SilcStack. */
716 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
718 int len = silc_buffer_truelen(dst);
719 int hlen = silc_buffer_headlen(dst);
724 /* Parse the arguments by formatting type. */
726 char *string = va_arg(va, char *);
732 if (string == (char *)SILC_PARAM_END)
735 slen = strlen(string);
736 d = silc_srealloc(stack, len + 1, dst->head,
737 sizeof(*dst->head) * (slen + len + 1));
738 if (silc_unlikely(!d))
741 memcpy(dst->head + len, string, slen);
743 dst->head[len] = '\0';
746 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
751 dst->end = dst->head + len;
752 dst->data = dst->head + hlen;
753 dst->tail = dst->end;