5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 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__, __x__, __req__) \
29 if (__req__ > silc_buffer_len((__x__))) \
30 if (!silc_buffer_srealloc_size((__s__), (__x__), \
31 silc_buffer_truelen((__x__)) + __req__)) \
36 /* Check that there is data to be unformatted */
37 #define UNFORMAT_HAS_SPACE(__x__, __req__) \
39 if (__req__ > silc_buffer_len((__x__))) \
41 if ((__req__ + 1) <= 0) \
46 /******************************* Formatting *********************************/
48 int silc_buffer_format(SilcBuffer dst, ...)
54 ret = silc_buffer_sformat_vp(NULL, dst, ap);
60 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
62 return silc_buffer_sformat_vp(NULL, dst, ap);
65 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
71 ret = silc_buffer_sformat_vp(stack, dst, ap);
77 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
79 SilcBufferParamType fmt;
81 SilcBool advance = FALSE;
83 /* Parse the arguments by formatting type. */
85 fmt = va_arg(ap, SilcBufferParamType);
88 case SILC_PARAM_OFFSET:
90 int offst = va_arg(ap, int);
94 if (offst > silc_buffer_len(dst))
96 silc_buffer_pull(dst, offst);
99 silc_buffer_push(dst, -(offst));
104 case SILC_PARAM_SI8_CHAR:
106 char x = (char)va_arg(ap, int);
107 FORMAT_HAS_SPACE(stack, dst, 1);
108 silc_buffer_put(dst, &x, 1);
109 silc_buffer_pull(dst, 1);
112 case SILC_PARAM_UI8_CHAR:
114 unsigned char x = (unsigned char)va_arg(ap, int);
115 FORMAT_HAS_SPACE(stack, dst, 1);
116 silc_buffer_put(dst, &x, 1);
117 silc_buffer_pull(dst, 1);
120 case SILC_PARAM_SI16_SHORT:
123 SilcInt16 x = (SilcInt16)va_arg(ap, int);
124 FORMAT_HAS_SPACE(stack, dst, 2);
125 SILC_PUT16_MSB(x, xf);
126 silc_buffer_put(dst, xf, 2);
127 silc_buffer_pull(dst, 2);
130 case SILC_PARAM_UI16_SHORT:
133 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
134 FORMAT_HAS_SPACE(stack, dst, 2);
135 SILC_PUT16_MSB(x, xf);
136 silc_buffer_put(dst, xf, 2);
137 silc_buffer_pull(dst, 2);
140 case SILC_PARAM_SI32_INT:
143 SilcInt32 x = va_arg(ap, SilcInt32);
144 FORMAT_HAS_SPACE(stack, dst, 4);
145 SILC_PUT32_MSB(x, xf);
146 silc_buffer_put(dst, xf, 4);
147 silc_buffer_pull(dst, 4);
150 case SILC_PARAM_UI32_INT:
153 SilcUInt32 x = va_arg(ap, SilcUInt32);
154 FORMAT_HAS_SPACE(stack, dst, 4);
155 SILC_PUT32_MSB(x, xf);
156 silc_buffer_put(dst, xf, 4);
157 silc_buffer_pull(dst, 4);
160 case SILC_PARAM_SI64_INT:
163 SilcInt64 x = va_arg(ap, SilcInt64);
164 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
165 SILC_PUT64_MSB(x, xf);
166 silc_buffer_put(dst, xf, sizeof(SilcInt64));
167 silc_buffer_pull(dst, sizeof(SilcInt64));
170 case SILC_PARAM_UI64_INT:
173 SilcUInt64 x = va_arg(ap, SilcUInt64);
174 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
175 SILC_PUT64_MSB(x, xf);
176 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
177 silc_buffer_pull(dst, sizeof(SilcUInt64));
180 case SILC_PARAM_UI8_STRING:
181 case SILC_PARAM_UI16_STRING:
182 case SILC_PARAM_UI32_STRING:
183 case SILC_PARAM_UI8_STRING_ALLOC:
184 case SILC_PARAM_UI16_STRING_ALLOC:
185 case SILC_PARAM_UI32_STRING_ALLOC:
187 unsigned char *x = va_arg(ap, unsigned char *);
188 SilcUInt32 tmp_len = strlen(x);
189 FORMAT_HAS_SPACE(stack, dst, tmp_len);
190 silc_buffer_put(dst, x, tmp_len);
191 silc_buffer_pull(dst, tmp_len);
194 case SILC_PARAM_UI8_NSTRING:
195 case SILC_PARAM_UI16_NSTRING:
196 case SILC_PARAM_UI32_NSTRING:
197 case SILC_PARAM_UI_XNSTRING:
198 case SILC_PARAM_DATA:
199 case SILC_PARAM_UI8_NSTRING_ALLOC:
200 case SILC_PARAM_UI16_NSTRING_ALLOC:
201 case SILC_PARAM_UI32_NSTRING_ALLOC:
202 case SILC_PARAM_UI_XNSTRING_ALLOC:
203 case SILC_PARAM_DATA_ALLOC:
205 unsigned char *x = va_arg(ap, unsigned char *);
206 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
208 FORMAT_HAS_SPACE(stack, dst, tmp_len);
209 silc_buffer_put(dst, x, tmp_len);
210 silc_buffer_pull(dst, tmp_len);
214 case SILC_PARAM_BUFFER:
215 case SILC_PARAM_BUFFER_ALLOC:
217 SilcBuffer x = va_arg(ap, SilcBuffer);
219 if (x && silc_buffer_len(x)) {
220 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
221 SILC_PUT32_MSB(silc_buffer_len(x), xf);
222 silc_buffer_put(dst, xf, 4);
223 silc_buffer_pull(dst, 4);
224 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
225 silc_buffer_pull(dst, silc_buffer_len(x));
232 case SILC_PARAM_ADVANCE:
236 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
237 "format the data.", fmt));
244 SILC_LOG_DEBUG(("Error occured while formatting data"));
246 silc_buffer_push(dst, flen);
250 /* Push the buffer back to where it belongs. */
252 silc_buffer_push(dst, flen);
257 /****************************** Unformatting ********************************/
259 int silc_buffer_unformat(SilcBuffer src, ...)
265 ret = silc_buffer_sunformat_vp(NULL, src, ap);
271 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
273 return silc_buffer_sunformat_vp(NULL, src, ap);
276 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
282 ret = silc_buffer_sunformat_vp(stack, src, ap);
288 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
290 SilcBufferParamType fmt;
291 unsigned char *start_ptr = src->data;
294 /* Parse the arguments by formatting type. */
296 fmt = va_arg(ap, SilcBufferParamType);
299 case SILC_PARAM_OFFSET:
301 int offst = va_arg(ap, int);
305 UNFORMAT_HAS_SPACE(src, offst);
306 silc_buffer_pull(src, offst);
308 silc_buffer_push(src, -(offst));
312 case SILC_PARAM_SI8_CHAR:
314 char *x = va_arg(ap, char *);
315 UNFORMAT_HAS_SPACE(src, 1);
318 silc_buffer_pull(src, 1);
321 case SILC_PARAM_UI8_CHAR:
323 unsigned char *x = va_arg(ap, unsigned char *);
324 UNFORMAT_HAS_SPACE(src, 1);
327 silc_buffer_pull(src, 1);
330 case SILC_PARAM_SI16_SHORT:
332 SilcInt16 *x = va_arg(ap, SilcInt16 *);
333 UNFORMAT_HAS_SPACE(src, 2);
335 SILC_GET16_MSB(*x, src->data);
336 silc_buffer_pull(src, 2);
339 case SILC_PARAM_UI16_SHORT:
341 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
342 UNFORMAT_HAS_SPACE(src, 2);
344 SILC_GET16_MSB(*x, src->data);
345 silc_buffer_pull(src, 2);
348 case SILC_PARAM_SI32_INT:
350 SilcInt32 *x = va_arg(ap, SilcInt32 *);
351 UNFORMAT_HAS_SPACE(src, 4);
353 SILC_GET32_MSB(*x, src->data);
354 silc_buffer_pull(src, 4);
357 case SILC_PARAM_UI32_INT:
359 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
360 UNFORMAT_HAS_SPACE(src, 4);
362 SILC_GET32_MSB(*x, src->data);
363 silc_buffer_pull(src, 4);
366 case SILC_PARAM_SI64_INT:
368 SilcInt64 *x = va_arg(ap, SilcInt64 *);
369 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
371 SILC_GET64_MSB(*x, src->data);
372 silc_buffer_pull(src, sizeof(SilcInt64));
375 case SILC_PARAM_UI64_INT:
377 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
378 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
380 SILC_GET64_MSB(*x, src->data);
381 silc_buffer_pull(src, sizeof(SilcUInt64));
384 case SILC_PARAM_UI8_STRING:
387 unsigned char **x = va_arg(ap, unsigned char **);
388 UNFORMAT_HAS_SPACE(src, 1);
389 len2 = (SilcUInt8)src->data[0];
390 silc_buffer_pull(src, 1);
391 UNFORMAT_HAS_SPACE(src, len2);
394 silc_buffer_pull(src, len2);
397 case SILC_PARAM_UI16_STRING:
400 unsigned char **x = va_arg(ap, unsigned char **);
401 UNFORMAT_HAS_SPACE(src, 2);
402 SILC_GET16_MSB(len2, src->data);
403 silc_buffer_pull(src, 2);
404 UNFORMAT_HAS_SPACE(src, len2);
407 silc_buffer_pull(src, len2);
410 case SILC_PARAM_UI8_STRING_ALLOC:
413 unsigned char **x = va_arg(ap, unsigned char **);
414 UNFORMAT_HAS_SPACE(src, 1);
415 len2 = (SilcUInt8)src->data[0];
416 silc_buffer_pull(src, 1);
417 UNFORMAT_HAS_SPACE(src, len2);
419 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
420 memcpy(*x, src->data, len2);
422 silc_buffer_pull(src, len2);
425 case SILC_PARAM_UI16_STRING_ALLOC:
428 unsigned char **x = va_arg(ap, unsigned char **);
429 UNFORMAT_HAS_SPACE(src, 2);
430 SILC_GET16_MSB(len2, src->data);
431 silc_buffer_pull(src, 2);
432 UNFORMAT_HAS_SPACE(src, len2);
434 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
435 memcpy(*x, src->data, len2);
437 silc_buffer_pull(src, len2);
440 case SILC_PARAM_UI32_STRING:
443 unsigned char **x = va_arg(ap, unsigned char **);
444 UNFORMAT_HAS_SPACE(src, 4);
445 SILC_GET32_MSB(len2, src->data);
446 silc_buffer_pull(src, 4);
447 UNFORMAT_HAS_SPACE(src, len2);
450 silc_buffer_pull(src, len2);
453 case SILC_PARAM_UI32_STRING_ALLOC:
456 unsigned char **x = va_arg(ap, unsigned char **);
457 UNFORMAT_HAS_SPACE(src, 4);
458 SILC_GET32_MSB(len2, src->data);
459 silc_buffer_pull(src, 4);
460 UNFORMAT_HAS_SPACE(src, len2);
462 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
463 memcpy(*x, src->data, len2);
465 silc_buffer_pull(src, len2);
468 case SILC_PARAM_UI8_NSTRING:
471 unsigned char **x = va_arg(ap, unsigned char **);
472 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
473 UNFORMAT_HAS_SPACE(src, 1);
474 len2 = (SilcUInt8)src->data[0];
475 silc_buffer_pull(src, 1);
476 UNFORMAT_HAS_SPACE(src, len2);
481 silc_buffer_pull(src, len2);
484 case SILC_PARAM_UI16_NSTRING:
487 unsigned char **x = va_arg(ap, unsigned char **);
488 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
489 UNFORMAT_HAS_SPACE(src, 2);
490 SILC_GET16_MSB(len2, src->data);
491 silc_buffer_pull(src, 2);
492 UNFORMAT_HAS_SPACE(src, len2);
497 silc_buffer_pull(src, len2);
500 case SILC_PARAM_UI8_NSTRING_ALLOC:
503 unsigned char **x = va_arg(ap, unsigned char **);
504 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
505 UNFORMAT_HAS_SPACE(src, 1);
506 len2 = (SilcUInt8)src->data[0];
507 silc_buffer_pull(src, 1);
508 UNFORMAT_HAS_SPACE(src, len2);
512 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
513 memcpy(*x, src->data, len2);
515 silc_buffer_pull(src, len2);
518 case SILC_PARAM_UI16_NSTRING_ALLOC:
521 unsigned char **x = va_arg(ap, unsigned char **);
522 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
523 UNFORMAT_HAS_SPACE(src, 2);
524 SILC_GET16_MSB(len2, src->data);
525 silc_buffer_pull(src, 2);
526 UNFORMAT_HAS_SPACE(src, len2);
530 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
531 memcpy(*x, src->data, len2);
533 silc_buffer_pull(src, len2);
536 case SILC_PARAM_UI32_NSTRING:
539 unsigned char **x = va_arg(ap, unsigned char **);
540 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
541 UNFORMAT_HAS_SPACE(src, 4);
542 SILC_GET32_MSB(len2, src->data);
543 silc_buffer_pull(src, 4);
544 UNFORMAT_HAS_SPACE(src, len2);
549 silc_buffer_pull(src, len2);
552 case SILC_PARAM_UI_XNSTRING:
553 case SILC_PARAM_DATA:
555 unsigned char **x = va_arg(ap, unsigned char **);
556 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
557 UNFORMAT_HAS_SPACE(src, len2);
560 silc_buffer_pull(src, len2);
563 case SILC_PARAM_UI_XNSTRING_ALLOC:
564 case SILC_PARAM_DATA_ALLOC:
566 unsigned char **x = va_arg(ap, unsigned char **);
567 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
568 UNFORMAT_HAS_SPACE(src, len2);
570 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
571 memcpy(*x, src->data, len2);
573 silc_buffer_pull(src, len2);
576 case SILC_PARAM_BUFFER:
578 SilcBuffer x = va_arg(ap, SilcBuffer);
580 UNFORMAT_HAS_SPACE(src, 4);
581 SILC_GET32_MSB(len2, src->data);
582 silc_buffer_pull(src, 4);
583 UNFORMAT_HAS_SPACE(src, len2);
584 silc_buffer_set(x, src->data, len2);
585 silc_buffer_pull(src, len2);
588 case SILC_PARAM_BUFFER_ALLOC:
590 SilcBuffer x = va_arg(ap, SilcBuffer);
592 UNFORMAT_HAS_SPACE(src, 4);
593 SILC_GET32_MSB(len2, src->data);
594 silc_buffer_pull(src, 4);
595 UNFORMAT_HAS_SPACE(src, len2);
596 silc_buffer_sformat(stack, x,
597 SILC_STR_DATA(src->data, len2),
599 silc_buffer_pull(src, len2);
605 case SILC_PARAM_ADVANCE:
608 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
609 "format the data.", fmt));
616 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
617 len = src->data - start_ptr;
618 silc_buffer_push(src, len);
622 /* Push the buffer back to the start. */
623 len = src->data - start_ptr;
624 silc_buffer_push(src, len);
629 /**************************** Utility functions *****************************/
631 /* Formats strings into a buffer */
633 int silc_buffer_strformat(SilcBuffer dst, ...)
635 int len = silc_buffer_truelen(dst);
636 int hlen = silc_buffer_headlen(dst);
641 /* Parse the arguments by formatting type. */
643 char *string = va_arg(va, char *);
649 if (string == (char *)SILC_PARAM_END)
652 slen = strlen(string);
653 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
657 memcpy(dst->head + len, string, slen);
659 dst->head[len] = '\0';
662 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
667 dst->end = dst->head + len;
668 dst->data = dst->head + hlen;
669 dst->tail = dst->end;
675 /* Formats strings into a buffer. Allocates memory from SilcStack. */
677 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
679 int len = silc_buffer_truelen(dst);
680 int hlen = silc_buffer_headlen(dst);
685 /* Parse the arguments by formatting type. */
687 char *string = va_arg(va, char *);
693 if (string == (char *)SILC_PARAM_END)
696 slen = strlen(string);
697 d = silc_srealloc_ua(stack, len + 1, dst->head,
698 sizeof(*dst->head) * (slen + len + 1));
702 memcpy(dst->head + len, string, slen);
704 dst->head[len] = '\0';
707 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
712 dst->end = dst->head + len;
713 dst->data = dst->head + hlen;
714 dst->tail = dst->end;