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_unformat_vp(src, ap);
271 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
273 SilcBufferParamType fmt;
274 unsigned char *start_ptr = src->data;
277 /* Parse the arguments by formatting type. */
279 fmt = va_arg(ap, SilcBufferParamType);
282 case SILC_PARAM_OFFSET:
284 int offst = va_arg(ap, int);
288 UNFORMAT_HAS_SPACE(src, offst);
289 silc_buffer_pull(src, offst);
291 silc_buffer_push(src, -(offst));
295 case SILC_PARAM_SI8_CHAR:
297 char *x = va_arg(ap, char *);
298 UNFORMAT_HAS_SPACE(src, 1);
301 silc_buffer_pull(src, 1);
304 case SILC_PARAM_UI8_CHAR:
306 unsigned char *x = va_arg(ap, unsigned char *);
307 UNFORMAT_HAS_SPACE(src, 1);
310 silc_buffer_pull(src, 1);
313 case SILC_PARAM_SI16_SHORT:
315 SilcInt16 *x = va_arg(ap, SilcInt16 *);
316 UNFORMAT_HAS_SPACE(src, 2);
318 SILC_GET16_MSB(*x, src->data);
319 silc_buffer_pull(src, 2);
322 case SILC_PARAM_UI16_SHORT:
324 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
325 UNFORMAT_HAS_SPACE(src, 2);
327 SILC_GET16_MSB(*x, src->data);
328 silc_buffer_pull(src, 2);
331 case SILC_PARAM_SI32_INT:
333 SilcInt32 *x = va_arg(ap, SilcInt32 *);
334 UNFORMAT_HAS_SPACE(src, 4);
336 SILC_GET32_MSB(*x, src->data);
337 silc_buffer_pull(src, 4);
340 case SILC_PARAM_UI32_INT:
342 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
343 UNFORMAT_HAS_SPACE(src, 4);
345 SILC_GET32_MSB(*x, src->data);
346 silc_buffer_pull(src, 4);
349 case SILC_PARAM_SI64_INT:
351 SilcInt64 *x = va_arg(ap, SilcInt64 *);
352 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
354 SILC_GET64_MSB(*x, src->data);
355 silc_buffer_pull(src, sizeof(SilcInt64));
358 case SILC_PARAM_UI64_INT:
360 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
361 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
363 SILC_GET64_MSB(*x, src->data);
364 silc_buffer_pull(src, sizeof(SilcUInt64));
367 case SILC_PARAM_UI8_STRING:
370 unsigned char **x = va_arg(ap, unsigned char **);
371 UNFORMAT_HAS_SPACE(src, 1);
372 len2 = (SilcUInt8)src->data[0];
373 silc_buffer_pull(src, 1);
374 UNFORMAT_HAS_SPACE(src, len2);
377 silc_buffer_pull(src, len2);
380 case SILC_PARAM_UI16_STRING:
383 unsigned char **x = va_arg(ap, unsigned char **);
384 UNFORMAT_HAS_SPACE(src, 2);
385 SILC_GET16_MSB(len2, src->data);
386 silc_buffer_pull(src, 2);
387 UNFORMAT_HAS_SPACE(src, len2);
390 silc_buffer_pull(src, len2);
393 case SILC_PARAM_UI8_STRING_ALLOC:
396 unsigned char **x = va_arg(ap, unsigned char **);
397 UNFORMAT_HAS_SPACE(src, 1);
398 len2 = (SilcUInt8)src->data[0];
399 silc_buffer_pull(src, 1);
400 UNFORMAT_HAS_SPACE(src, len2);
402 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
403 memcpy(*x, src->data, len2);
405 silc_buffer_pull(src, len2);
408 case SILC_PARAM_UI16_STRING_ALLOC:
411 unsigned char **x = va_arg(ap, unsigned char **);
412 UNFORMAT_HAS_SPACE(src, 2);
413 SILC_GET16_MSB(len2, src->data);
414 silc_buffer_pull(src, 2);
415 UNFORMAT_HAS_SPACE(src, len2);
417 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
418 memcpy(*x, src->data, len2);
420 silc_buffer_pull(src, len2);
423 case SILC_PARAM_UI32_STRING:
426 unsigned char **x = va_arg(ap, unsigned char **);
427 UNFORMAT_HAS_SPACE(src, 4);
428 SILC_GET32_MSB(len2, src->data);
429 silc_buffer_pull(src, 4);
430 UNFORMAT_HAS_SPACE(src, len2);
433 silc_buffer_pull(src, len2);
436 case SILC_PARAM_UI32_STRING_ALLOC:
439 unsigned char **x = va_arg(ap, unsigned char **);
440 UNFORMAT_HAS_SPACE(src, 4);
441 SILC_GET32_MSB(len2, src->data);
442 silc_buffer_pull(src, 4);
443 UNFORMAT_HAS_SPACE(src, len2);
445 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
446 memcpy(*x, src->data, len2);
448 silc_buffer_pull(src, len2);
451 case SILC_PARAM_UI8_NSTRING:
454 unsigned char **x = va_arg(ap, unsigned char **);
455 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
456 UNFORMAT_HAS_SPACE(src, 1);
457 len2 = (SilcUInt8)src->data[0];
458 silc_buffer_pull(src, 1);
459 UNFORMAT_HAS_SPACE(src, len2);
464 silc_buffer_pull(src, len2);
467 case SILC_PARAM_UI16_NSTRING:
470 unsigned char **x = va_arg(ap, unsigned char **);
471 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
472 UNFORMAT_HAS_SPACE(src, 2);
473 SILC_GET16_MSB(len2, src->data);
474 silc_buffer_pull(src, 2);
475 UNFORMAT_HAS_SPACE(src, len2);
480 silc_buffer_pull(src, len2);
483 case SILC_PARAM_UI8_NSTRING_ALLOC:
486 unsigned char **x = va_arg(ap, unsigned char **);
487 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
488 UNFORMAT_HAS_SPACE(src, 1);
489 len2 = (SilcUInt8)src->data[0];
490 silc_buffer_pull(src, 1);
491 UNFORMAT_HAS_SPACE(src, len2);
495 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
496 memcpy(*x, src->data, len2);
498 silc_buffer_pull(src, len2);
501 case SILC_PARAM_UI16_NSTRING_ALLOC:
504 unsigned char **x = va_arg(ap, unsigned char **);
505 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
506 UNFORMAT_HAS_SPACE(src, 2);
507 SILC_GET16_MSB(len2, src->data);
508 silc_buffer_pull(src, 2);
509 UNFORMAT_HAS_SPACE(src, len2);
513 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
514 memcpy(*x, src->data, len2);
516 silc_buffer_pull(src, len2);
519 case SILC_PARAM_UI32_NSTRING:
522 unsigned char **x = va_arg(ap, unsigned char **);
523 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
524 UNFORMAT_HAS_SPACE(src, 4);
525 SILC_GET32_MSB(len2, src->data);
526 silc_buffer_pull(src, 4);
527 UNFORMAT_HAS_SPACE(src, len2);
532 silc_buffer_pull(src, len2);
535 case SILC_PARAM_UI_XNSTRING:
536 case SILC_PARAM_DATA:
538 unsigned char **x = va_arg(ap, unsigned char **);
539 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
540 UNFORMAT_HAS_SPACE(src, len2);
543 silc_buffer_pull(src, len2);
546 case SILC_PARAM_UI_XNSTRING_ALLOC:
547 case SILC_PARAM_DATA_ALLOC:
549 unsigned char **x = va_arg(ap, unsigned char **);
550 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
551 UNFORMAT_HAS_SPACE(src, len2);
553 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
554 memcpy(*x, src->data, len2);
556 silc_buffer_pull(src, len2);
559 case SILC_PARAM_BUFFER:
561 SilcBuffer x = va_arg(ap, SilcBuffer);
563 UNFORMAT_HAS_SPACE(src, 4);
564 SILC_GET32_MSB(len2, src->data);
565 silc_buffer_pull(src, 4);
566 UNFORMAT_HAS_SPACE(src, len2);
567 silc_buffer_set(x, src->data, len2);
568 silc_buffer_pull(src, len2);
571 case SILC_PARAM_BUFFER_ALLOC:
573 SilcBuffer x = va_arg(ap, SilcBuffer);
575 UNFORMAT_HAS_SPACE(src, 4);
576 SILC_GET32_MSB(len2, src->data);
577 silc_buffer_pull(src, 4);
578 UNFORMAT_HAS_SPACE(src, len2);
579 silc_buffer_format(x,
580 SILC_STR_DATA(src->data, len2),
582 silc_buffer_pull(src, len2);
588 case SILC_PARAM_ADVANCE:
591 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
592 "format the data.", fmt));
599 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
600 len = src->data - start_ptr;
601 silc_buffer_push(src, len);
605 /* Push the buffer back to the start. */
606 len = src->data - start_ptr;
607 silc_buffer_push(src, len);
612 /**************************** Utility functions *****************************/
614 /* Formats strings into a buffer */
616 int silc_buffer_strformat(SilcBuffer dst, ...)
618 int len = silc_buffer_truelen(dst);
619 int hlen = silc_buffer_headlen(dst);
624 /* Parse the arguments by formatting type. */
626 char *string = va_arg(va, char *);
632 if (string == (char *)SILC_PARAM_END)
635 slen = strlen(string);
636 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
640 memcpy(dst->head + len, string, slen);
642 dst->head[len] = '\0';
645 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
650 dst->end = dst->head + len;
651 dst->data = dst->head + hlen;
652 dst->tail = dst->end;
658 /* Formats strings into a buffer. Allocates memory from SilcStack. */
660 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
662 int len = silc_buffer_truelen(dst);
663 int hlen = silc_buffer_headlen(dst);
668 /* Parse the arguments by formatting type. */
670 char *string = va_arg(va, char *);
676 if (string == (char *)SILC_PARAM_END)
679 slen = strlen(string);
680 d = silc_srealloc_ua(stack, len + 1, dst->head,
681 sizeof(*dst->head) * (slen + len + 1));
685 memcpy(dst->head + len, string, slen);
687 dst->head[len] = '\0';
690 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
695 dst->end = dst->head + len;
696 dst->data = dst->head + hlen;
697 dst->tail = dst->end;