Static analyzer fixes
[silc.git] / lib / silcutil / silcbuffmt.c
1 /*
2
3   silcbuffmt.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2014 Pekka Riikonen
8
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.
12
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.
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
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
58 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
59 {
60   return silc_buffer_sformat_vp(NULL, dst, ap);
61 }
62
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
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
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
298 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
299 {
300   return silc_buffer_sunformat_vp(NULL, src, ap);
301 }
302
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
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
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
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 }