1 /*
2
3 silcbuffmt.c
4
5 Author: Pekka Riikonen <priikone@silcnet.org>
6
7 Copyright (C) 1997 - 2014 Pekka Riikonen
8
9 The contents of this file are subject to one of the Licenses specified
10 in the COPYING file; You may not use this file except in compliance
11 with the License.
12
13 The software distributed under the License is distributed on an "AS IS"
14 basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15 KIND, either expressed or implied. See the COPYING file for more
16 information.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22
23 /************************** Types and definitions ***************************/
24
25 /* Check that buffer has enough room to format data in it, if not
26 allocate more. */
27 #define FORMAT_HAS_SPACE(s, b, req) \
28 do { \
29 if (silc_unlikely(!silc_buffer_senlarge(s, b, req))) \
30 goto fail; \
31 flen += req; \
32 } while(0)
33
34 /* Check that there is data to be unformatted */
35 #define UNFORMAT_HAS_SPACE(b, req) \
36 do { \
37 if (silc_unlikely(req > silc_buffer_len(b))) \
38 goto fail; \
39 if (silc_unlikely((req + 1) <= 0)) \
40 goto fail; \
41 } while(0)
42
43
44 /******************************* Formatting *********************************/
45
silc_buffer_format(SilcBuffer dst,...)46 int silc_buffer_format(SilcBuffer dst, ...)
47 {
48 va_list ap;
49 int ret;
50
51 va_start(ap, dst);
52 ret = silc_buffer_sformat_vp(NULL, dst, ap);
53 va_end(ap);
54
55 return ret;
56 }
57
silc_buffer_format_vp(SilcBuffer dst,va_list ap)58 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
59 {
60 return silc_buffer_sformat_vp(NULL, dst, ap);
61 }
62
silc_buffer_sformat(SilcStack stack,SilcBuffer dst,...)63 int silc_buffer_sformat(SilcStack stack, SilcBuffer dst, ...)
64 {
65 va_list ap;
66 int ret;
67
68 va_start(ap, dst);
69 ret = silc_buffer_sformat_vp(stack, dst, ap);
70 va_end(ap);
71
72 return ret;
73 }
74
silc_buffer_sformat_vp(SilcStack stack,SilcBuffer dst,va_list ap)75 int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
76 {
77 SilcBufferParamType fmt;
78 int flen = 0;
79 SilcBool advance = FALSE;
80
81 /* Parse the arguments by formatting type. */
82 while (1) {
83 fmt = va_arg(ap, SilcBufferParamType);
84
85 switch(fmt) {
86 case SILC_PARAM_FUNC:
87 {
88 SilcBufferFormatFunc func = NULL;
89 SilcBufferSFormatFunc funcs = NULL;
90 void *val;
91 void *context;
92 int tmp_len;
93 if (!stack)
94 func = va_arg(ap, SilcBufferFormatFunc);
95 else
96 funcs = va_arg(ap, SilcBufferSFormatFunc);
97 val = va_arg(ap, void *);
98 context = va_arg(ap, void *);
99 if (!stack)
100 tmp_len = func(dst, val, context);
101 else
102 tmp_len = funcs(stack, dst, val, context);
103 if (tmp_len < 0)
104 goto fail;
105 if (tmp_len) {
106 silc_buffer_pull(dst, tmp_len);
107 flen += tmp_len;
108 }
109 }
110 break;
111 case SILC_PARAM_UI8_STRING:
112 case SILC_PARAM_UI16_STRING:
113 case SILC_PARAM_UI32_STRING:
114 case SILC_PARAM_UI8_STRING_ALLOC:
115 case SILC_PARAM_UI16_STRING_ALLOC:
116 case SILC_PARAM_UI32_STRING_ALLOC:
117 {
118 unsigned char *x = va_arg(ap, unsigned char *);
119 SilcUInt32 tmp_len = x ? strlen(x) : 0;
120 if (x && tmp_len) {
121 FORMAT_HAS_SPACE(stack, dst, tmp_len);
122 silc_buffer_put(dst, x, tmp_len);
123 silc_buffer_pull(dst, tmp_len);
124 }
125 break;
126 }
127 case SILC_PARAM_UI8_NSTRING:
128 case SILC_PARAM_UI16_NSTRING:
129 case SILC_PARAM_UI32_NSTRING:
130 case SILC_PARAM_UI_XNSTRING:
131 case SILC_PARAM_DATA:
132 case SILC_PARAM_UI8_NSTRING_ALLOC:
133 case SILC_PARAM_UI16_NSTRING_ALLOC:
134 case SILC_PARAM_UI32_NSTRING_ALLOC:
135 case SILC_PARAM_UI_XNSTRING_ALLOC:
136 case SILC_PARAM_DATA_ALLOC:
137 {
138 unsigned char *x = va_arg(ap, unsigned char *);
139 SilcUInt32 tmp_len = va_arg(ap, SilcUInt32);
140 if (x && tmp_len) {
141 FORMAT_HAS_SPACE(stack, dst, tmp_len);
142 silc_buffer_put(dst, x, tmp_len);
143 silc_buffer_pull(dst, tmp_len);
144 }
145 break;
146 }
147 case SILC_PARAM_UI8_CHAR:
148 {
149 unsigned char x = (unsigned char)va_arg(ap, int);
150 FORMAT_HAS_SPACE(stack, dst, 1);
151 silc_buffer_put(dst, &x, 1);
152 silc_buffer_pull(dst, 1);
153 break;
154 }
155 case SILC_PARAM_UI16_SHORT:
156 {
157 unsigned char xf[2];
158 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
159 FORMAT_HAS_SPACE(stack, dst, 2);
160 SILC_PUT16_MSB(x, xf);
161 silc_buffer_put(dst, xf, 2);
162 silc_buffer_pull(dst, 2);
163 break;
164 }
165 case SILC_PARAM_UI32_INT:
166 {
167 unsigned char xf[4];
168 SilcUInt32 x = va_arg(ap, SilcUInt32);
169 FORMAT_HAS_SPACE(stack, dst, 4);
170 SILC_PUT32_MSB(x, xf);
171 silc_buffer_put(dst, xf, 4);
172 silc_buffer_pull(dst, 4);
173 break;
174 }
175 case SILC_PARAM_UI64_INT:
176 {
177 unsigned char xf[8];
178 SilcUInt64 x = va_arg(ap, SilcUInt64);
179 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcUInt64));
180 SILC_PUT64_MSB(x, xf);
181 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
182 silc_buffer_pull(dst, sizeof(SilcUInt64));
183 break;
184 }
185 case SILC_PARAM_SI8_CHAR:
186 {
187 char x = (char)va_arg(ap, int);
188 FORMAT_HAS_SPACE(stack, dst, 1);
189 silc_buffer_put(dst, &x, 1);
190 silc_buffer_pull(dst, 1);
191 break;
192 }
193 case SILC_PARAM_SI16_SHORT:
194 {
195 unsigned char xf[2];
196 SilcInt16 x = (SilcInt16)va_arg(ap, int);
197 FORMAT_HAS_SPACE(stack, dst, 2);
198 SILC_PUT16_MSB(x, xf);
199 silc_buffer_put(dst, xf, 2);
200 silc_buffer_pull(dst, 2);
201 break;
202 }
203 case SILC_PARAM_SI32_INT:
204 {
205 unsigned char xf[4];
206 SilcInt32 x = va_arg(ap, SilcInt32);
207 FORMAT_HAS_SPACE(stack, dst, 4);
208 SILC_PUT32_MSB(x, xf);
209 silc_buffer_put(dst, xf, 4);
210 silc_buffer_pull(dst, 4);
211 break;
212 }
213 case SILC_PARAM_SI64_INT:
214 {
215 unsigned char xf[8];
216 SilcInt64 x = va_arg(ap, SilcInt64);
217 FORMAT_HAS_SPACE(stack, dst, sizeof(SilcInt64));
218 SILC_PUT64_MSB(x, xf);
219 silc_buffer_put(dst, xf, sizeof(SilcInt64));
220 silc_buffer_pull(dst, sizeof(SilcInt64));
221 break;
222 }
223 case SILC_PARAM_BUFFER:
224 case SILC_PARAM_BUFFER_ALLOC:
225 {
226 SilcBuffer x = va_arg(ap, SilcBuffer);
227 unsigned char xf[4];
228 if (x && silc_buffer_len(x)) {
229 FORMAT_HAS_SPACE(stack, dst, silc_buffer_len(x) + 4);
230 SILC_PUT32_MSB(silc_buffer_len(x), xf);
231 silc_buffer_put(dst, xf, 4);
232 silc_buffer_pull(dst, 4);
233 silc_buffer_put(dst, silc_buffer_data(x), silc_buffer_len(x));
234 silc_buffer_pull(dst, silc_buffer_len(x));
235 }
236 }
237 break;
238 case SILC_PARAM_OFFSET:
239 {
240 int offst = va_arg(ap, int);
241 if (!offst)
242 break;
243 if (offst > 1) {
244 if (offst > silc_buffer_len(dst))
245 goto fail;
246 silc_buffer_pull(dst, offst);
247 flen += offst;
248 } else {
249 if (-(offst) > (int)silc_buffer_headlen(dst))
250 goto fail;
251 silc_buffer_push(dst, -(offst));
252 flen += -(offst);
253 }
254 break;
255 }
256 case SILC_PARAM_ADVANCE:
257 advance = TRUE;
258 break;
259 case SILC_PARAM_END:
260 goto ok;
261 break;
262 default:
263 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
264 "format the data.", fmt));
265 goto fail;
266 break;
267 }
268 }
269
270 fail:
271 SILC_LOG_DEBUG(("Error occured while formatting data"));
272 if (!advance)
273 silc_buffer_push(dst, flen);
274 return -1;
275
276 ok:
277 /* Push the buffer back to where it belongs. */
278 if (!advance)
279 silc_buffer_push(dst, flen);
280 return flen;
281 }
282
283
284 /****************************** Unformatting ********************************/
285
silc_buffer_unformat(SilcBuffer src,...)286 int silc_buffer_unformat(SilcBuffer src, ...)
287 {
288 va_list ap;
289 int ret;
290
291 va_start(ap, src);
292 ret = silc_buffer_sunformat_vp(NULL, src, ap);
293 va_end(ap);
294
295 return ret;
296 }
297
silc_buffer_unformat_vp(SilcBuffer src,va_list ap)298 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
299 {
300 return silc_buffer_sunformat_vp(NULL, src, ap);
301 }
302
silc_buffer_sunformat(SilcStack stack,SilcBuffer src,...)303 int silc_buffer_sunformat(SilcStack stack, SilcBuffer src, ...)
304 {
305 va_list ap;
306 int ret;
307
308 va_start(ap, src);
309 ret = silc_buffer_sunformat_vp(stack, src, ap);
310 va_end(ap);
311
312 return ret;
313 }
314
silc_buffer_sunformat_vp(SilcStack stack,SilcBuffer src,va_list ap)315 int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
316 {
317 SilcBufferParamType fmt;
318 unsigned char *start_ptr = src->data;
319 int len = 0;
320 SilcBool advance = FALSE;
321
322 /* Parse the arguments by formatting type. */
323 while(1) {
324 fmt = va_arg(ap, SilcBufferParamType);
325
326 switch(fmt) {
327 case SILC_PARAM_FUNC:
328 {
329 SilcBufferUnformatFunc func = NULL;
330 SilcBufferSUnformatFunc funcs = NULL;
331 void **val;
332 void *context;
333 int tmp_len;
334 if (!stack)
335 func = va_arg(ap, SilcBufferUnformatFunc);
336 else
337 funcs = va_arg(ap, SilcBufferSUnformatFunc);
338 val = va_arg(ap, void **);
339 context = va_arg(ap, void *);
340 if (!stack)
341 tmp_len = func(src, val, context);
342 else
343 tmp_len = funcs(stack, src, val, context);
344 if (tmp_len < 0)
345 goto fail;
346 if (tmp_len) {
347 UNFORMAT_HAS_SPACE(src, tmp_len);
348 silc_buffer_pull(src, tmp_len);
349 }
350 }
351 case SILC_PARAM_UI_XNSTRING:
352 case SILC_PARAM_DATA:
353 {
354 unsigned char **x = va_arg(ap, unsigned char **);
355 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
356 UNFORMAT_HAS_SPACE(src, len2);
357 if (silc_likely(len2 && x))
358 *x = src->data;
359 silc_buffer_pull(src, len2);
360 break;
361 }
362 case SILC_PARAM_UI_XNSTRING_ALLOC:
363 case SILC_PARAM_DATA_ALLOC:
364 {
365 unsigned char **x = va_arg(ap, unsigned char **);
366 SilcUInt32 len2 = va_arg(ap, SilcUInt32);
367 UNFORMAT_HAS_SPACE(src, len2);
368 if (silc_likely(len2 && x)) {
369 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
370 if (*x)
371 memcpy(*x, src->data, len2);
372 }
373 silc_buffer_pull(src, len2);
374 break;
375 }
376 case SILC_PARAM_UI8_CHAR:
377 {
378 unsigned char *x = va_arg(ap, unsigned char *);
379 UNFORMAT_HAS_SPACE(src, 1);
380 if (silc_likely(x))
381 *x = src->data[0];
382 silc_buffer_pull(src, 1);
383 break;
384 }
385 case SILC_PARAM_UI16_SHORT:
386 {
387 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
388 UNFORMAT_HAS_SPACE(src, 2);
389 if (silc_likely(x))
390 SILC_GET16_MSB(*x, src->data);
391 silc_buffer_pull(src, 2);
392 break;
393 }
394 case SILC_PARAM_UI32_INT:
395 {
396 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
397 UNFORMAT_HAS_SPACE(src, 4);
398 if (silc_likely(x))
399 SILC_GET32_MSB(*x, src->data);
400 silc_buffer_pull(src, 4);
401 break;
402 }
403 case SILC_PARAM_UI64_INT:
404 {
405 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
406 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
407 if (silc_likely(x))
408 SILC_GET64_MSB(*x, src->data);
409 silc_buffer_pull(src, sizeof(SilcUInt64));
410 break;
411 }
412 case SILC_PARAM_SI8_CHAR:
413 {
414 char *x = va_arg(ap, char *);
415 UNFORMAT_HAS_SPACE(src, 1);
416 if (silc_likely(x))
417 *x = src->data[0];
418 silc_buffer_pull(src, 1);
419 break;
420 }
421 case SILC_PARAM_SI16_SHORT:
422 {
423 SilcInt16 *x = va_arg(ap, SilcInt16 *);
424 UNFORMAT_HAS_SPACE(src, 2);
425 if (silc_likely(x))
426 SILC_GET16_MSB(*x, src->data);
427 silc_buffer_pull(src, 2);
428 break;
429 }
430 case SILC_PARAM_SI32_INT:
431 {
432 SilcInt32 *x = va_arg(ap, SilcInt32 *);
433 UNFORMAT_HAS_SPACE(src, 4);
434 if (silc_likely(x))
435 SILC_GET32_MSB(*x, src->data);
436 silc_buffer_pull(src, 4);
437 break;
438 }
439 case SILC_PARAM_SI64_INT:
440 {
441 SilcInt64 *x = va_arg(ap, SilcInt64 *);
442 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
443 if (silc_likely(x))
444 SILC_GET64_MSB(*x, src->data);
445 silc_buffer_pull(src, sizeof(SilcInt64));
446 break;
447 }
448 case SILC_PARAM_UI8_STRING:
449 {
450 SilcUInt8 len2;
451 unsigned char **x = va_arg(ap, unsigned char **);
452 UNFORMAT_HAS_SPACE(src, 1);
453 len2 = (SilcUInt8)src->data[0];
454 silc_buffer_pull(src, 1);
455 UNFORMAT_HAS_SPACE(src, len2);
456 if (silc_likely(x))
457 *x = src->data;
458 silc_buffer_pull(src, len2);
459 break;
460 }
461 case SILC_PARAM_UI16_STRING:
462 {
463 SilcUInt16 len2;
464 unsigned char **x = va_arg(ap, unsigned char **);
465 UNFORMAT_HAS_SPACE(src, 2);
466 SILC_GET16_MSB(len2, src->data);
467 silc_buffer_pull(src, 2);
468 UNFORMAT_HAS_SPACE(src, len2);
469 if (silc_likely(x))
470 *x = src->data;
471 silc_buffer_pull(src, len2);
472 break;
473 }
474 case SILC_PARAM_UI8_STRING_ALLOC:
475 {
476 SilcUInt8 len2;
477 unsigned char **x = va_arg(ap, unsigned char **);
478 UNFORMAT_HAS_SPACE(src, 1);
479 len2 = (SilcUInt8)src->data[0];
480 silc_buffer_pull(src, 1);
481 UNFORMAT_HAS_SPACE(src, len2);
482 if (silc_likely(x && len2)) {
483 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
484 if (*x)
485 memcpy(*x, src->data, len2);
486 }
487 silc_buffer_pull(src, len2);
488 break;
489 }
490 case SILC_PARAM_UI16_STRING_ALLOC:
491 {
492 SilcUInt16 len2;
493 unsigned char **x = va_arg(ap, unsigned char **);
494 UNFORMAT_HAS_SPACE(src, 2);
495 SILC_GET16_MSB(len2, src->data);
496 silc_buffer_pull(src, 2);
497 UNFORMAT_HAS_SPACE(src, len2);
498 if (silc_likely(x && len2)) {
499 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
500 if (*x)
501 memcpy(*x, src->data, len2);
502 }
503 silc_buffer_pull(src, len2);
504 break;
505 }
506 case SILC_PARAM_UI32_STRING:
507 {
508 SilcUInt32 len2;
509 unsigned char **x = va_arg(ap, unsigned char **);
510 UNFORMAT_HAS_SPACE(src, 4);
511 SILC_GET32_MSB(len2, src->data);
512 silc_buffer_pull(src, 4);
513 UNFORMAT_HAS_SPACE(src, len2);
514 if (silc_likely(x))
515 *x = src->data;
516 silc_buffer_pull(src, len2);
517 break;
518 }
519 case SILC_PARAM_UI32_STRING_ALLOC:
520 {
521 SilcUInt32 len2;
522 unsigned char **x = va_arg(ap, unsigned char **);
523 UNFORMAT_HAS_SPACE(src, 4);
524 SILC_GET32_MSB(len2, src->data);
525 silc_buffer_pull(src, 4);
526 UNFORMAT_HAS_SPACE(src, len2);
527 if (silc_likely(x && len2)) {
528 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
529 if (*x)
530 memcpy(*x, src->data, len2);
531 }
532 silc_buffer_pull(src, len2);
533 break;
534 }
535 case SILC_PARAM_UI8_NSTRING:
536 {
537 SilcUInt8 len2;
538 unsigned char **x = va_arg(ap, unsigned char **);
539 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
540 UNFORMAT_HAS_SPACE(src, 1);
541 len2 = (SilcUInt8)src->data[0];
542 silc_buffer_pull(src, 1);
543 UNFORMAT_HAS_SPACE(src, len2);
544 if (len3)
545 *len3 = len2;
546 if (x)
547 *x = src->data;
548 silc_buffer_pull(src, len2);
549 break;
550 }
551 case SILC_PARAM_UI16_NSTRING:
552 {
553 SilcUInt16 len2;
554 unsigned char **x = va_arg(ap, unsigned char **);
555 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
556 UNFORMAT_HAS_SPACE(src, 2);
557 SILC_GET16_MSB(len2, src->data);
558 silc_buffer_pull(src, 2);
559 UNFORMAT_HAS_SPACE(src, len2);
560 if (len3)
561 *len3 = len2;
562 if (x)
563 *x = src->data;
564 silc_buffer_pull(src, len2);
565 break;
566 }
567 case SILC_PARAM_UI8_NSTRING_ALLOC:
568 {
569 SilcUInt8 len2;
570 unsigned char **x = va_arg(ap, unsigned char **);
571 SilcUInt8 *len3 = va_arg(ap, SilcUInt8 *);
572 UNFORMAT_HAS_SPACE(src, 1);
573 len2 = (SilcUInt8)src->data[0];
574 silc_buffer_pull(src, 1);
575 UNFORMAT_HAS_SPACE(src, len2);
576 if (len3)
577 *len3 = len2;
578 if (x && len2) {
579 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
580 if (*x)
581 memcpy(*x, src->data, len2);
582 }
583 silc_buffer_pull(src, len2);
584 break;
585 }
586 case SILC_PARAM_UI16_NSTRING_ALLOC:
587 {
588 SilcUInt16 len2;
589 unsigned char **x = va_arg(ap, unsigned char **);
590 SilcUInt16 *len3 = va_arg(ap, SilcUInt16 *);
591 UNFORMAT_HAS_SPACE(src, 2);
592 SILC_GET16_MSB(len2, src->data);
593 silc_buffer_pull(src, 2);
594 UNFORMAT_HAS_SPACE(src, len2);
595 if (len3)
596 *len3 = len2;
597 if (x && len2) {
598 *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
599 if (*x)
600 memcpy(*x, src->data, len2);
601 }
602 silc_buffer_pull(src, len2);
603 break;
604 }
605 case SILC_PARAM_UI32_NSTRING:
606 {
607 SilcUInt32 len2;
608 unsigned char **x = va_arg(ap, unsigned char **);
609 SilcUInt32 *len3 = va_arg(ap, SilcUInt32 *);
610 UNFORMAT_HAS_SPACE(src, 4);
611 SILC_GET32_MSB(len2, src->data);
612 silc_buffer_pull(src, 4);
613 UNFORMAT_HAS_SPACE(src, len2);
614 if (len3)
615 *len3 = len2;
616 if (x)
617 *x = src->data;
618 silc_buffer_pull(src, len2);
619 break;
620 }
621 case SILC_PARAM_BUFFER:
622 {
623 SilcBuffer x = va_arg(ap, SilcBuffer);
624 SilcUInt32 len2;
625 UNFORMAT_HAS_SPACE(src, 4);
626 SILC_GET32_MSB(len2, src->data);
627 silc_buffer_pull(src, 4);
628 UNFORMAT_HAS_SPACE(src, len2);
629 silc_buffer_set(x, src->data, len2);
630 silc_buffer_pull(src, len2);
631 }
632 break;
633 case SILC_PARAM_BUFFER_ALLOC:
634 {
635 SilcBuffer x = va_arg(ap, SilcBuffer);
636 SilcUInt32 len2;
637 UNFORMAT_HAS_SPACE(src, 4);
638 SILC_GET32_MSB(len2, src->data);
639 silc_buffer_pull(src, 4);
640 UNFORMAT_HAS_SPACE(src, len2);
641 if (silc_buffer_sformat(stack, x,
642 SILC_STR_DATA(src->data, len2),
643 SILC_STR_END) < 0)
644 goto fail;
645 silc_buffer_pull(src, len2);
646 }
647 break;
648 case SILC_PARAM_OFFSET:
649 {
650 int offst = va_arg(ap, int);
651 if (!offst)
652 break;
653 if (offst > 1) {
654 UNFORMAT_HAS_SPACE(src, offst);
655 silc_buffer_pull(src, offst);
656 } else {
657 silc_buffer_push(src, -(offst));
658 }
659 break;
660 }
661 case SILC_PARAM_ADVANCE:
662 advance = TRUE;
663 break;
664 case SILC_PARAM_END:
665 goto ok;
666 break;
667 default:
668 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
669 "format the data.", fmt));
670 goto fail;
671 break;
672 }
673 }
674
675 fail:
676 SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
677 len = src->data - start_ptr;
678 silc_buffer_push(src, len);
679 return -1;
680
681 ok:
682 /* Push the buffer back to the start. */
683 if (!advance) {
684 len = src->data - start_ptr;
685 silc_buffer_push(src, len);
686 }
687 return len;
688 }
689
690
691 /**************************** Utility functions *****************************/
692
693 /* Formats strings into a buffer */
694
silc_buffer_strformat(SilcBuffer dst,...)695 int silc_buffer_strformat(SilcBuffer dst, ...)
696 {
697 int len = silc_buffer_truelen(dst);
698 int hlen = silc_buffer_headlen(dst);
699 va_list va;
700
701 va_start(va, dst);
702
703 /* Parse the arguments by formatting type. */
704 while(1) {
705 char *string = va_arg(va, char *);
706 unsigned char *d;
707 SilcInt32 slen;
708
709 if (!string)
710 continue;
711 if (string == (char *)SILC_PARAM_END)
712 goto ok;
713
714 slen = strlen(string);
715 d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
716 if (silc_unlikely(!d))
717 return -1;
718 dst->head = d;
719 memcpy(dst->head + len, string, slen);
720 len += slen;
721 dst->head[len] = '\0';
722 }
723
724 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
725 va_end(va);
726 return -1;
727
728 ok:
729 dst->end = dst->head + len;
730 dst->data = dst->head + hlen;
731 dst->tail = dst->end;
732
733 va_end(va);
734 return len;
735 }
736
737 /* Formats strings into a buffer. Allocates memory from SilcStack. */
738
silc_buffer_sstrformat(SilcStack stack,SilcBuffer dst,...)739 int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
740 {
741 int len = silc_buffer_truelen(dst);
742 int hlen = silc_buffer_headlen(dst);
743 va_list va;
744
745 va_start(va, dst);
746
747 /* Parse the arguments by formatting type. */
748 while(1) {
749 char *string = va_arg(va, char *);
750 unsigned char *d;
751 SilcInt32 slen;
752
753 if (!string)
754 continue;
755 if (string == (char *)SILC_PARAM_END)
756 goto ok;
757
758 slen = strlen(string);
759 d = silc_srealloc(stack, len + 1, dst->head,
760 sizeof(*dst->head) * (slen + len + 1));
761 if (silc_unlikely(!d))
762 return -1;
763 dst->head = d;
764 memcpy(dst->head + len, string, slen);
765 len += slen;
766 dst->head[len] = '\0';
767 }
768
769 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
770 va_end(va);
771 return -1;
772
773 ok:
774 dst->end = dst->head + len;
775 dst->data = dst->head + hlen;
776 dst->tail = dst->end;
777
778 va_end(va);
779 return len;
780 }
781