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_BUFFER_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_BUFFER_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_BUFFER_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_BUFFER_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_BUFFER_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_BUFFER_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_BUFFER_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_BUFFER_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_BUFFER_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_BUFFER_PARAM_UI8_STRING:
181 case SILC_BUFFER_PARAM_UI16_STRING:
182 case SILC_BUFFER_PARAM_UI32_STRING:
183 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
184 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
185 case SILC_BUFFER_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_BUFFER_PARAM_UI8_NSTRING:
195 case SILC_BUFFER_PARAM_UI16_NSTRING:
196 case SILC_BUFFER_PARAM_UI32_NSTRING:
197 case SILC_BUFFER_PARAM_UI_XNSTRING:
198 case SILC_BUFFER_PARAM_DATA:
199 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
200 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
201 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
202 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
203 case SILC_BUFFER_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_BUFFER_PARAM_END:
217 case SILC_BUFFER_PARAM_ADVANCE:
221 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
222 "format the data.", fmt));
229 SILC_LOG_DEBUG(("Error occured while formatting data"));
231 silc_buffer_push(dst, flen);
235 /* Push the buffer back to where it belongs. */
237 silc_buffer_push(dst, flen);
242 /****************************** Unformatting ********************************/
244 int silc_buffer_unformat(SilcBuffer src, ...)
250 ret = silc_buffer_unformat_vp(src, ap);
256 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
258 SilcBufferParamType fmt;
259 unsigned char *start_ptr = src->data;
262 /* Parse the arguments by formatting type. */
264 fmt = va_arg(ap, SilcBufferParamType);
267 case SILC_BUFFER_PARAM_OFFSET:
269 int offst = va_arg(ap, int);
273 UNFORMAT_HAS_SPACE(src, offst);
274 silc_buffer_pull(src, offst);
276 silc_buffer_push(src, -(offst));
280 case SILC_BUFFER_PARAM_SI8_CHAR:
282 char *x = va_arg(ap, char *);
283 UNFORMAT_HAS_SPACE(src, 1);
286 silc_buffer_pull(src, 1);
289 case SILC_BUFFER_PARAM_UI8_CHAR:
291 unsigned char *x = va_arg(ap, unsigned char *);
292 UNFORMAT_HAS_SPACE(src, 1);
295 silc_buffer_pull(src, 1);
298 case SILC_BUFFER_PARAM_SI16_SHORT:
300 SilcInt16 *x = va_arg(ap, SilcInt16 *);
301 UNFORMAT_HAS_SPACE(src, 2);
303 SILC_GET16_MSB(*x, src->data);
304 silc_buffer_pull(src, 2);
307 case SILC_BUFFER_PARAM_UI16_SHORT:
309 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
310 UNFORMAT_HAS_SPACE(src, 2);
312 SILC_GET16_MSB(*x, src->data);
313 silc_buffer_pull(src, 2);
316 case SILC_BUFFER_PARAM_SI32_INT:
318 SilcInt32 *x = va_arg(ap, SilcInt32 *);
319 UNFORMAT_HAS_SPACE(src, 4);
321 SILC_GET32_MSB(*x, src->data);
322 silc_buffer_pull(src, 4);
325 case SILC_BUFFER_PARAM_UI32_INT:
327 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
328 UNFORMAT_HAS_SPACE(src, 4);
330 SILC_GET32_MSB(*x, src->data);
331 silc_buffer_pull(src, 4);
334 case SILC_BUFFER_PARAM_SI64_INT:
336 SilcInt64 *x = va_arg(ap, SilcInt64 *);
337 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
339 SILC_GET64_MSB(*x, src->data);
340 silc_buffer_pull(src, sizeof(SilcInt64));
343 case SILC_BUFFER_PARAM_UI64_INT:
345 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
346 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
348 SILC_GET64_MSB(*x, src->data);
349 silc_buffer_pull(src, sizeof(SilcUInt64));
352 case SILC_BUFFER_PARAM_UI8_STRING:
355 unsigned char **x = va_arg(ap, unsigned char **);
356 UNFORMAT_HAS_SPACE(src, 1);
357 len2 = (SilcUInt8)src->data[0];
358 silc_buffer_pull(src, 1);
359 UNFORMAT_HAS_SPACE(src, len2);
362 silc_buffer_pull(src, len2);
365 case SILC_BUFFER_PARAM_UI16_STRING:
368 unsigned char **x = va_arg(ap, unsigned char **);
369 UNFORMAT_HAS_SPACE(src, 2);
370 SILC_GET16_MSB(len2, src->data);
371 silc_buffer_pull(src, 2);
372 UNFORMAT_HAS_SPACE(src, len2);
375 silc_buffer_pull(src, len2);
378 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
381 unsigned char **x = va_arg(ap, unsigned char **);
382 UNFORMAT_HAS_SPACE(src, 1);
383 len2 = (SilcUInt8)src->data[0];
384 silc_buffer_pull(src, 1);
385 UNFORMAT_HAS_SPACE(src, len2);
387 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
388 memcpy(*x, src->data, len2);
390 silc_buffer_pull(src, len2);
393 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
396 unsigned char **x = va_arg(ap, unsigned char **);
397 UNFORMAT_HAS_SPACE(src, 2);
398 SILC_GET16_MSB(len2, src->data);
399 silc_buffer_pull(src, 2);
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_BUFFER_PARAM_UI32_STRING:
411 unsigned char **x = va_arg(ap, unsigned char **);
412 UNFORMAT_HAS_SPACE(src, 4);
413 SILC_GET32_MSB(len2, src->data);
414 silc_buffer_pull(src, 4);
415 UNFORMAT_HAS_SPACE(src, len2);
418 silc_buffer_pull(src, len2);
421 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
424 unsigned char **x = va_arg(ap, unsigned char **);
425 UNFORMAT_HAS_SPACE(src, 4);
426 SILC_GET32_MSB(len2, src->data);
427 silc_buffer_pull(src, 4);
428 UNFORMAT_HAS_SPACE(src, len2);
430 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
431 memcpy(*x, src->data, len2);
433 silc_buffer_pull(src, len2);
436 case SILC_BUFFER_PARAM_UI8_NSTRING:
439 unsigned char **x = va_arg(ap, unsigned char **);
440 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
441 UNFORMAT_HAS_SPACE(src, 1);
442 len2 = (SilcUInt8)src->data[0];
443 silc_buffer_pull(src, 1);
444 UNFORMAT_HAS_SPACE(src, len2);
449 silc_buffer_pull(src, len2);
452 case SILC_BUFFER_PARAM_UI16_NSTRING:
455 unsigned char **x = va_arg(ap, unsigned char **);
456 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
457 UNFORMAT_HAS_SPACE(src, 2);
458 SILC_GET16_MSB(len2, src->data);
459 silc_buffer_pull(src, 2);
460 UNFORMAT_HAS_SPACE(src, len2);
465 silc_buffer_pull(src, len2);
468 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
471 unsigned char **x = va_arg(ap, unsigned char **);
472 SilcUInt8 *len = 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);
480 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
481 memcpy(*x, src->data, len2);
483 silc_buffer_pull(src, len2);
486 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
489 unsigned char **x = va_arg(ap, unsigned char **);
490 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
491 UNFORMAT_HAS_SPACE(src, 2);
492 SILC_GET16_MSB(len2, src->data);
493 silc_buffer_pull(src, 2);
494 UNFORMAT_HAS_SPACE(src, len2);
498 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
499 memcpy(*x, src->data, len2);
501 silc_buffer_pull(src, len2);
504 case SILC_BUFFER_PARAM_UI32_NSTRING:
507 unsigned char **x = va_arg(ap, unsigned char **);
508 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
509 UNFORMAT_HAS_SPACE(src, 4);
510 SILC_GET32_MSB(len2, src->data);
511 silc_buffer_pull(src, 4);
512 UNFORMAT_HAS_SPACE(src, len2);
517 silc_buffer_pull(src, len2);
520 case SILC_BUFFER_PARAM_UI_XNSTRING:
521 case SILC_BUFFER_PARAM_DATA:
523 unsigned char **x = va_arg(ap, unsigned char **);
524 SilcUInt32 len = va_arg(ap, SilcUInt32);
525 UNFORMAT_HAS_SPACE(src, len);
528 silc_buffer_pull(src, len);
531 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
532 case SILC_BUFFER_PARAM_DATA_ALLOC:
534 unsigned char **x = va_arg(ap, unsigned char **);
535 SilcUInt32 len = va_arg(ap, SilcUInt32);
536 UNFORMAT_HAS_SPACE(src, len);
538 *x = silc_calloc(len + 1, sizeof(unsigned char));
539 memcpy(*x, src->data, len);
541 silc_buffer_pull(src, len);
544 case SILC_BUFFER_PARAM_END:
547 case SILC_BUFFER_PARAM_ADVANCE:
550 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
551 "format the data.", fmt));
558 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
559 len = src->data - start_ptr;
560 silc_buffer_push(src, len);
564 /* Push the buffer back to the start. */
565 len = src->data - start_ptr;
566 silc_buffer_push(src, len);
571 /**************************** Utility functions *****************************/
573 /* Formats strings into a buffer */
575 int silc_buffer_strformat(SilcBuffer dst, ...)
577 int len = silc_buffer_truelen(dst);
578 int hlen = silc_buffer_headlen(dst);
583 /* Parse the arguments by formatting type. */
585 char *string = va_arg(va, char *);
591 if (string == (char *)SILC_BUFFER_PARAM_END)
594 slen = strlen(string);
595 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
599 memcpy(dst->head + len, string, slen);
601 dst->head[len] = '\0';
604 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
609 dst->end = dst->head + len;
610 dst->data = dst->head + hlen;
611 dst->tail = dst->end;
617 /* Formats strings into a buffer. Allocates memory from SilcStack. */
619 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
621 int len = silc_buffer_truelen(dst);
626 /* Parse the arguments by formatting type. */
628 char *string = va_arg(va, char *);
634 if (string == (char *)SILC_BUFFER_PARAM_END)
637 slen = strlen(string);
638 d = silc_srealloc_ua(stack, len + 1, dst->head,
639 sizeof(*dst->head) * (slen + len + 1));
643 memcpy(dst->head + len, string, slen);
645 dst->head[len] = '\0';
648 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
653 dst->end = dst->head + len;
654 dst->data = dst->head;
655 dst->tail = dst->end;