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;
82 /* Parse the arguments by formatting type. */
84 fmt = va_arg(ap, SilcBufferParamType);
87 case SILC_BUFFER_PARAM_OFFSET:
89 int offst = va_arg(ap, int);
93 if (offst > silc_buffer_len(dst))
95 silc_buffer_pull(dst, offst);
98 silc_buffer_push(dst, -(offst));
103 case SILC_BUFFER_PARAM_SI8_CHAR:
105 char x = (char)va_arg(ap, int);
106 FORMAT_HAS_SPACE(stack, dst, 1);
107 silc_buffer_put(dst, &x, 1);
108 silc_buffer_pull(dst, 1);
111 case SILC_BUFFER_PARAM_UI8_CHAR:
113 unsigned char x = (unsigned char)va_arg(ap, int);
114 FORMAT_HAS_SPACE(stack, dst, 1);
115 silc_buffer_put(dst, &x, 1);
116 silc_buffer_pull(dst, 1);
119 case SILC_BUFFER_PARAM_SI16_SHORT:
122 SilcInt16 x = (SilcInt16)va_arg(ap, int);
123 FORMAT_HAS_SPACE(stack, dst, 2);
124 SILC_PUT16_MSB(x, xf);
125 silc_buffer_put(dst, xf, 2);
126 silc_buffer_pull(dst, 2);
129 case SILC_BUFFER_PARAM_UI16_SHORT:
132 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
133 FORMAT_HAS_SPACE(stack, dst, 2);
134 SILC_PUT16_MSB(x, xf);
135 silc_buffer_put(dst, xf, 2);
136 silc_buffer_pull(dst, 2);
139 case SILC_BUFFER_PARAM_SI32_INT:
142 SilcInt32 x = va_arg(ap, SilcInt32);
143 FORMAT_HAS_SPACE(stack, dst, 4);
144 SILC_PUT32_MSB(x, xf);
145 silc_buffer_put(dst, xf, 4);
146 silc_buffer_pull(dst, 4);
149 case SILC_BUFFER_PARAM_UI32_INT:
152 SilcUInt32 x = va_arg(ap, SilcUInt32);
153 FORMAT_HAS_SPACE(stack, dst, 4);
154 SILC_PUT32_MSB(x, xf);
155 silc_buffer_put(dst, xf, 4);
156 silc_buffer_pull(dst, 4);
159 case SILC_BUFFER_PARAM_SI64_INT:
162 SilcInt64 x = va_arg(ap, SilcInt64);
163 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
164 SILC_PUT64_MSB(x, xf);
165 silc_buffer_put(dst, xf, sizeof(SilcInt64));
166 silc_buffer_pull(dst, sizeof(SilcInt64));
169 case SILC_BUFFER_PARAM_UI64_INT:
172 SilcUInt64 x = va_arg(ap, SilcUInt64);
173 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
174 SILC_PUT64_MSB(x, xf);
175 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
176 silc_buffer_pull(dst, sizeof(SilcUInt64));
179 case SILC_BUFFER_PARAM_UI8_STRING:
180 case SILC_BUFFER_PARAM_UI16_STRING:
181 case SILC_BUFFER_PARAM_UI32_STRING:
182 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
183 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
184 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
186 unsigned char *x = va_arg(ap, unsigned char *);
187 SilcUInt32 tmp_len = strlen(x);
188 FORMAT_HAS_SPACE(stack, dst, tmp_len);
189 silc_buffer_put(dst, x, tmp_len);
190 silc_buffer_pull(dst, tmp_len);
193 case SILC_BUFFER_PARAM_UI8_NSTRING:
194 case SILC_BUFFER_PARAM_UI16_NSTRING:
195 case SILC_BUFFER_PARAM_UI32_NSTRING:
196 case SILC_BUFFER_PARAM_UI_XNSTRING:
197 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
198 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
199 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
200 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
202 unsigned char *x = va_arg(ap, unsigned char *);
203 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
205 FORMAT_HAS_SPACE(stack, dst, tmp_len);
206 silc_buffer_put(dst, x, tmp_len);
207 silc_buffer_pull(dst, tmp_len);
211 case SILC_BUFFER_PARAM_END:
215 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
216 "format the data.", fmt));
223 SILC_LOG_DEBUG(("Error occured while formatting data"));
224 silc_buffer_push(dst, flen);
228 /* Push the buffer back to where it belongs. */
229 silc_buffer_push(dst, flen);
234 /****************************** Unformatting ********************************/
236 int silc_buffer_unformat(SilcBuffer src, ...)
242 ret = silc_buffer_unformat_vp(src, ap);
248 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
250 SilcBufferParamType fmt;
251 unsigned char *start_ptr = src->data;
254 /* Parse the arguments by formatting type. */
256 fmt = va_arg(ap, SilcBufferParamType);
259 case SILC_BUFFER_PARAM_OFFSET:
261 int offst = va_arg(ap, int);
265 UNFORMAT_HAS_SPACE(src, offst);
266 silc_buffer_pull(src, offst);
268 silc_buffer_push(src, -(offst));
272 case SILC_BUFFER_PARAM_SI8_CHAR:
274 char *x = va_arg(ap, char *);
275 UNFORMAT_HAS_SPACE(src, 1);
278 silc_buffer_pull(src, 1);
281 case SILC_BUFFER_PARAM_UI8_CHAR:
283 unsigned char *x = va_arg(ap, unsigned char *);
284 UNFORMAT_HAS_SPACE(src, 1);
287 silc_buffer_pull(src, 1);
290 case SILC_BUFFER_PARAM_SI16_SHORT:
292 SilcInt16 *x = va_arg(ap, SilcInt16 *);
293 UNFORMAT_HAS_SPACE(src, 2);
295 SILC_GET16_MSB(*x, src->data);
296 silc_buffer_pull(src, 2);
299 case SILC_BUFFER_PARAM_UI16_SHORT:
301 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
302 UNFORMAT_HAS_SPACE(src, 2);
304 SILC_GET16_MSB(*x, src->data);
305 silc_buffer_pull(src, 2);
308 case SILC_BUFFER_PARAM_SI32_INT:
310 SilcInt32 *x = va_arg(ap, SilcInt32 *);
311 UNFORMAT_HAS_SPACE(src, 4);
313 SILC_GET32_MSB(*x, src->data);
314 silc_buffer_pull(src, 4);
317 case SILC_BUFFER_PARAM_UI32_INT:
319 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
320 UNFORMAT_HAS_SPACE(src, 4);
322 SILC_GET32_MSB(*x, src->data);
323 silc_buffer_pull(src, 4);
326 case SILC_BUFFER_PARAM_SI64_INT:
328 SilcInt64 *x = va_arg(ap, SilcInt64 *);
329 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
331 SILC_GET64_MSB(*x, src->data);
332 silc_buffer_pull(src, sizeof(SilcInt64));
335 case SILC_BUFFER_PARAM_UI64_INT:
337 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
338 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
340 SILC_GET64_MSB(*x, src->data);
341 silc_buffer_pull(src, sizeof(SilcUInt64));
344 case SILC_BUFFER_PARAM_UI8_STRING:
347 unsigned char **x = va_arg(ap, unsigned char **);
348 UNFORMAT_HAS_SPACE(src, 1);
349 len2 = (SilcUInt8)src->data[0];
350 silc_buffer_pull(src, 1);
351 UNFORMAT_HAS_SPACE(src, len2);
354 silc_buffer_pull(src, len2);
357 case SILC_BUFFER_PARAM_UI16_STRING:
360 unsigned char **x = va_arg(ap, unsigned char **);
361 UNFORMAT_HAS_SPACE(src, 2);
362 SILC_GET16_MSB(len2, src->data);
363 silc_buffer_pull(src, 2);
364 UNFORMAT_HAS_SPACE(src, len2);
367 silc_buffer_pull(src, len2);
370 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
373 unsigned char **x = va_arg(ap, unsigned char **);
374 UNFORMAT_HAS_SPACE(src, 1);
375 len2 = (SilcUInt8)src->data[0];
376 silc_buffer_pull(src, 1);
377 UNFORMAT_HAS_SPACE(src, len2);
379 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
380 memcpy(*x, src->data, len2);
382 silc_buffer_pull(src, len2);
385 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
388 unsigned char **x = va_arg(ap, unsigned char **);
389 UNFORMAT_HAS_SPACE(src, 2);
390 SILC_GET16_MSB(len2, src->data);
391 silc_buffer_pull(src, 2);
392 UNFORMAT_HAS_SPACE(src, len2);
394 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
395 memcpy(*x, src->data, len2);
397 silc_buffer_pull(src, len2);
400 case SILC_BUFFER_PARAM_UI32_STRING:
403 unsigned char **x = va_arg(ap, unsigned char **);
404 UNFORMAT_HAS_SPACE(src, 4);
405 SILC_GET32_MSB(len2, src->data);
406 silc_buffer_pull(src, 4);
407 UNFORMAT_HAS_SPACE(src, len2);
410 silc_buffer_pull(src, len2);
413 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
416 unsigned char **x = va_arg(ap, unsigned char **);
417 UNFORMAT_HAS_SPACE(src, 4);
418 SILC_GET32_MSB(len2, src->data);
419 silc_buffer_pull(src, 4);
420 UNFORMAT_HAS_SPACE(src, len2);
422 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
423 memcpy(*x, src->data, len2);
425 silc_buffer_pull(src, len2);
428 case SILC_BUFFER_PARAM_UI8_NSTRING:
431 unsigned char **x = va_arg(ap, unsigned char **);
432 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
433 UNFORMAT_HAS_SPACE(src, 1);
434 len2 = (SilcUInt8)src->data[0];
435 silc_buffer_pull(src, 1);
436 UNFORMAT_HAS_SPACE(src, len2);
441 silc_buffer_pull(src, len2);
444 case SILC_BUFFER_PARAM_UI16_NSTRING:
447 unsigned char **x = va_arg(ap, unsigned char **);
448 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
449 UNFORMAT_HAS_SPACE(src, 2);
450 SILC_GET16_MSB(len2, src->data);
451 silc_buffer_pull(src, 2);
452 UNFORMAT_HAS_SPACE(src, len2);
457 silc_buffer_pull(src, len2);
460 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
463 unsigned char **x = va_arg(ap, unsigned char **);
464 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
465 UNFORMAT_HAS_SPACE(src, 1);
466 len2 = (SilcUInt8)src->data[0];
467 silc_buffer_pull(src, 1);
468 UNFORMAT_HAS_SPACE(src, len2);
472 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
473 memcpy(*x, src->data, len2);
475 silc_buffer_pull(src, len2);
478 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
481 unsigned char **x = va_arg(ap, unsigned char **);
482 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
483 UNFORMAT_HAS_SPACE(src, 2);
484 SILC_GET16_MSB(len2, src->data);
485 silc_buffer_pull(src, 2);
486 UNFORMAT_HAS_SPACE(src, len2);
490 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
491 memcpy(*x, src->data, len2);
493 silc_buffer_pull(src, len2);
496 case SILC_BUFFER_PARAM_UI32_NSTRING:
499 unsigned char **x = va_arg(ap, unsigned char **);
500 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
501 UNFORMAT_HAS_SPACE(src, 4);
502 SILC_GET32_MSB(len2, src->data);
503 silc_buffer_pull(src, 4);
504 UNFORMAT_HAS_SPACE(src, len2);
509 silc_buffer_pull(src, len2);
512 case SILC_BUFFER_PARAM_UI_XNSTRING:
514 unsigned char **x = va_arg(ap, unsigned char **);
515 SilcUInt32 len = va_arg(ap, SilcUInt32);
516 UNFORMAT_HAS_SPACE(src, len);
519 silc_buffer_pull(src, len);
522 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
524 unsigned char **x = va_arg(ap, unsigned char **);
525 SilcUInt32 len = va_arg(ap, SilcUInt32);
526 UNFORMAT_HAS_SPACE(src, len);
528 *x = silc_calloc(len + 1, sizeof(unsigned char));
529 memcpy(*x, src->data, len);
531 silc_buffer_pull(src, len);
534 case SILC_BUFFER_PARAM_END:
538 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
539 "format the data.", fmt));
546 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
547 len = src->data - start_ptr;
548 silc_buffer_push(src, len);
552 /* Push the buffer back to the start. */
553 len = src->data - start_ptr;
554 silc_buffer_push(src, len);
559 /**************************** Utility functions *****************************/
561 /* Formats strings into a buffer */
563 int silc_buffer_strformat(SilcBuffer dst, ...)
565 int len = silc_buffer_truelen(dst);
570 /* Parse the arguments by formatting type. */
572 char *string = va_arg(va, char *);
578 if (string == (char *)SILC_BUFFER_PARAM_END)
581 slen = strlen(string);
582 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
586 memcpy(dst->head + len, string, slen);
588 dst->head[len] = '\0';
591 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
596 dst->end = dst->head + len;
597 dst->data = dst->head;
598 dst->tail = dst->end;
604 /* Formats strings into a buffer. Allocates memory from SilcStack. */
606 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
608 int len = silc_buffer_truelen(dst);
613 /* Parse the arguments by formatting type. */
615 char *string = va_arg(va, char *);
621 if (string == (char *)SILC_BUFFER_PARAM_END)
624 slen = strlen(string);
625 d = silc_srealloc_ua(stack, len + 1, dst->head,
626 sizeof(*dst->head) * (slen + len + 1));
630 memcpy(dst->head + len, string, slen);
632 dst->head[len] = '\0';
635 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
640 dst->end = dst->head + len;
641 dst->data = dst->head;
642 dst->tail = dst->end;