Integer type name change.
[silc.git] / lib / silcutil / silcbuffmt.c
1 /*
2
3   silcbuffmt.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "silcincludes.h"
23
24 /* Macro to check whether there is enough free space to add the
25    required amount of data. For unformatting this means that there must
26    be the data that is to be extracted. */
27 #define HAS_SPACE(x, req)                       \
28 do {                                            \
29   if (req > (x)->len)                           \
30     goto fail;                                  \
31 } while(0)
32
33 /* Formats the arguments sent and puts them into the buffer sent as
34    argument. The buffer must be initialized beforehand and it must have
35    enough free space to include the formatted data. If this function
36    fails caller should not trust the buffer anymore and should free it. 
37    This function is used, for example, to create packets to send over
38    network. */
39
40 int silc_buffer_format(SilcBuffer dst, ...)
41 {
42   va_list ap;
43   int ret;
44
45   va_start(ap, dst);
46   ret = silc_buffer_format_vp(dst, ap);
47   va_end(ap);
48
49   return ret;
50 }
51
52 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
53 {
54   SilcBufferParamType fmt;
55   unsigned char *start_ptr = dst->data;
56   int len;
57
58   /* Parse the arguments by formatting type. */
59   while(1) {
60     fmt = va_arg(ap, SilcBufferParamType);
61
62     switch(fmt) {
63     case SILC_BUFFER_PARAM_SI8_CHAR:
64       {
65         char x = (char)va_arg(ap, int);
66         HAS_SPACE(dst, 1);
67         silc_buffer_put(dst, &x, 1);
68         silc_buffer_pull(dst, 1);
69         break;
70       }
71     case SILC_BUFFER_PARAM_UI8_CHAR:
72       {
73         unsigned char x = (unsigned char)va_arg(ap, int);
74         HAS_SPACE(dst, 1);
75         silc_buffer_put(dst, &x, 1);
76         silc_buffer_pull(dst, 1);
77         break;
78       }
79     case SILC_BUFFER_PARAM_SI16_SHORT:
80       {
81         unsigned char xf[2];
82         SilcInt16 x = (SilcInt16)va_arg(ap, int);
83         HAS_SPACE(dst, 2);
84         SILC_PUT16_MSB(x, xf);
85         silc_buffer_put(dst, xf, 2);
86         silc_buffer_pull(dst, 2);
87         break;
88       }
89     case SILC_BUFFER_PARAM_UI16_SHORT:
90       {
91         unsigned char xf[2];
92         SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
93         HAS_SPACE(dst, 2);
94         SILC_PUT16_MSB(x, xf);
95         silc_buffer_put(dst, xf, 2);
96         silc_buffer_pull(dst, 2);
97         break;
98       }
99     case SILC_BUFFER_PARAM_SI32_INT:
100       {
101         unsigned char xf[4];
102         SilcInt32 x = va_arg(ap, SilcInt32);
103         HAS_SPACE(dst, 4);
104         SILC_PUT32_MSB(x, xf);
105         silc_buffer_put(dst, xf, 4);
106         silc_buffer_pull(dst, 4);
107         break;
108       }
109     case SILC_BUFFER_PARAM_UI32_INT:
110       {
111         unsigned char xf[4];
112         SilcUInt32 x = va_arg(ap, SilcUInt32);
113         HAS_SPACE(dst, 4);
114         SILC_PUT32_MSB(x, xf);
115         silc_buffer_put(dst, xf, 4);
116         silc_buffer_pull(dst, 4);
117         break;
118       }
119     case SILC_BUFFER_PARAM_SI64_INT:
120       {
121         unsigned char xf[8];
122         SilcInt64 x = va_arg(ap, SilcInt64);
123         HAS_SPACE(dst, 8);
124         SILC_PUT64_MSB(x, xf);
125         silc_buffer_put(dst, xf, 8);
126         silc_buffer_pull(dst, 8);
127         break;
128       }
129     case SILC_BUFFER_PARAM_UI64_INT:
130       {
131         unsigned char xf[8];
132         SilcUInt64 x = va_arg(ap, SilcUInt64);
133         HAS_SPACE(dst, 8);
134         SILC_PUT64_MSB(x, xf);
135         silc_buffer_put(dst, xf, 8);
136         silc_buffer_pull(dst, 8);
137         break;
138       }
139     case SILC_BUFFER_PARAM_UI8_STRING:
140     case SILC_BUFFER_PARAM_UI16_STRING:
141     case SILC_BUFFER_PARAM_UI32_STRING:
142     case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
143     case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
144     case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
145       {
146         unsigned char *x = va_arg(ap, unsigned char *);
147         SilcUInt32 tmp_len = strlen(x);
148         HAS_SPACE(dst, tmp_len);
149         silc_buffer_put(dst, x, tmp_len);
150         silc_buffer_pull(dst, tmp_len);
151         break;
152       }
153     case SILC_BUFFER_PARAM_UI8_NSTRING:
154     case SILC_BUFFER_PARAM_UI16_NSTRING:
155     case SILC_BUFFER_PARAM_UI32_NSTRING:
156     case SILC_BUFFER_PARAM_UI_XNSTRING:
157     case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
158     case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
159     case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
160     case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
161       {
162         unsigned char *x = va_arg(ap, unsigned char *);
163         SilcUInt32 len = va_arg(ap, SilcUInt32);
164         HAS_SPACE(dst, len);
165         silc_buffer_put(dst, x, len);
166         silc_buffer_pull(dst, len);
167         break;
168       }
169     case SILC_BUFFER_PARAM_END:
170       goto ok;
171       break;
172     default:
173       SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
174                       "format the data.", fmt));
175       goto fail;
176       break;
177     }
178   }
179
180  fail:
181   SILC_LOG_DEBUG(("Error occured while formatting data"));
182   return -1;
183
184  ok:
185   /* Push the buffer back to where it belongs. */
186   len = dst->data - start_ptr;
187   silc_buffer_push(dst, len);
188   return len;
189 }
190
191 /* Unformats the buffer sent as argument. The unformatted data is returned
192    to the variable argument list of pointers. The buffer must point to the
193    start of the data area to be unformatted. Buffer maybe be safely free'd
194    after this returns succesfully. */
195
196 int silc_buffer_unformat(SilcBuffer src, ...)
197 {
198   va_list ap;
199   int ret;
200
201   va_start(ap, src);
202   ret = silc_buffer_unformat_vp(src, ap);
203   va_end(ap);
204   
205   return ret;
206 }
207
208 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
209 {
210   SilcBufferParamType fmt;
211   unsigned char *start_ptr = src->data;
212   int len = 0;
213
214   /* Parse the arguments by formatting type. */
215   while(1) {
216     fmt = va_arg(ap, SilcBufferParamType);
217
218     switch(fmt) {
219     case SILC_BUFFER_PARAM_SI8_CHAR:
220       {
221         char *x = va_arg(ap, char *);
222         HAS_SPACE(src, 1);
223         if (x)
224           *x = src->data[0];
225         silc_buffer_pull(src, 1);
226         break;
227       }
228     case SILC_BUFFER_PARAM_UI8_CHAR:
229       {
230         unsigned char *x = va_arg(ap, unsigned char *);
231         HAS_SPACE(src, 1);
232         if (x)
233           *x = src->data[0];
234         silc_buffer_pull(src, 1);
235         break;
236       }
237     case SILC_BUFFER_PARAM_SI16_SHORT:
238       {
239         SilcInt16 *x = va_arg(ap, SilcInt16 *);
240         HAS_SPACE(src, 2);
241         if (x)
242           SILC_GET16_MSB(*x, src->data);
243         silc_buffer_pull(src, 2);
244         break;
245       }
246     case SILC_BUFFER_PARAM_UI16_SHORT:
247       {
248         SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
249         HAS_SPACE(src, 2);
250         if (x)
251           SILC_GET16_MSB(*x, src->data);
252         silc_buffer_pull(src, 2);
253         break;
254       }
255     case SILC_BUFFER_PARAM_SI32_INT:
256       {
257         SilcInt32 *x = va_arg(ap, SilcInt32 *);
258         HAS_SPACE(src, 4);
259         if (x)
260           SILC_GET32_MSB(*x, src->data);
261         silc_buffer_pull(src, 4);
262         break;
263       }
264     case SILC_BUFFER_PARAM_UI32_INT:
265       {
266         SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
267         HAS_SPACE(src, 4);
268         if (x)
269           SILC_GET32_MSB(*x, src->data);
270         silc_buffer_pull(src, 4);
271         break;
272       }
273     case SILC_BUFFER_PARAM_SI64_INT:
274       {
275         SilcInt64 *x = va_arg(ap, SilcInt64 *);
276         HAS_SPACE(src, 8);
277         if (x)
278           SILC_GET64_MSB(*x, src->data);
279         silc_buffer_pull(src, 8);
280         break;
281       }
282     case SILC_BUFFER_PARAM_UI64_INT:
283       {
284         SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
285         HAS_SPACE(src, 8);
286         if (x)
287           SILC_GET64_MSB(*x, src->data);
288         silc_buffer_pull(src, 8);
289         break;
290       }
291     case SILC_BUFFER_PARAM_UI8_STRING:
292       {
293         SilcUInt8 len2;
294         unsigned char **x = va_arg(ap, unsigned char **);
295         HAS_SPACE(src, 1);
296         len2 = (SilcUInt8)src->data[0];
297         silc_buffer_pull(src, 1);
298         HAS_SPACE(src, len2);
299         if (x)
300           *x = src->data;
301         silc_buffer_pull(src, len2);
302         break;
303       }
304     case SILC_BUFFER_PARAM_UI16_STRING:
305       {
306         SilcUInt16 len2;
307         unsigned char **x = va_arg(ap, unsigned char **);
308         HAS_SPACE(src, 2);
309         SILC_GET16_MSB(len2, src->data);
310         silc_buffer_pull(src, 2);
311         HAS_SPACE(src, len2);
312         if (x)
313           *x = src->data;
314         silc_buffer_pull(src, len2);
315         break;
316       }
317     case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
318       {
319         SilcUInt8 len2;
320         unsigned char **x = va_arg(ap, unsigned char **);
321         HAS_SPACE(src, 1);
322         len2 = (SilcUInt8)src->data[0];
323         silc_buffer_pull(src, 1);
324         HAS_SPACE(src, len2);
325         if (x && len2) {
326           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
327           memcpy(*x, src->data, len2);
328         }
329         silc_buffer_pull(src, len2);
330         break;
331       }
332     case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
333       {
334         SilcUInt16 len2;
335         unsigned char **x = va_arg(ap, unsigned char **);
336         HAS_SPACE(src, 2);
337         SILC_GET16_MSB(len2, src->data);
338         silc_buffer_pull(src, 2);
339         HAS_SPACE(src, len2);
340         if (x && len2) {
341           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
342           memcpy(*x, src->data, len2);
343         }
344         silc_buffer_pull(src, len2);
345         break;
346       }
347     case SILC_BUFFER_PARAM_UI32_STRING:
348       {
349         SilcUInt32 len2;
350         unsigned char **x = va_arg(ap, unsigned char **);
351         HAS_SPACE(src, 4);
352         SILC_GET32_MSB(len2, src->data);
353         silc_buffer_pull(src, 4);
354         HAS_SPACE(src, len2);
355         if (x)
356           *x = src->data;
357         silc_buffer_pull(src, len2);
358         break;
359       }
360     case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
361       {
362         SilcUInt32 len2;
363         unsigned char **x = va_arg(ap, unsigned char **);
364         HAS_SPACE(src, 4);
365         SILC_GET32_MSB(len2, src->data);
366         silc_buffer_pull(src, 4);
367         HAS_SPACE(src, len2);
368         if (x && len2) {
369           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
370           memcpy(*x, src->data, len2);
371         }
372         silc_buffer_pull(src, len2);
373         break;
374       }
375     case SILC_BUFFER_PARAM_UI8_NSTRING:
376       {
377         SilcUInt8 len2;
378         unsigned char **x = va_arg(ap, unsigned char **);
379         SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
380         HAS_SPACE(src, 1);
381         len2 = (SilcUInt8)src->data[0];
382         silc_buffer_pull(src, 1);
383         HAS_SPACE(src, len2);
384         if (len)
385           *len = len2;
386         if (x)
387           *x = src->data;
388         silc_buffer_pull(src, len2);
389         break;
390       }
391     case SILC_BUFFER_PARAM_UI16_NSTRING:
392       {
393         SilcUInt16 len2;
394         unsigned char **x = va_arg(ap, unsigned char **);
395         SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
396         HAS_SPACE(src, 2);
397         SILC_GET16_MSB(len2, src->data);
398         silc_buffer_pull(src, 2);
399         HAS_SPACE(src, len2);
400         if (len)
401           *len = len2;
402         if (x)
403           *x = src->data;
404         silc_buffer_pull(src, len2);
405         break;
406       }
407     case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
408       {
409         SilcUInt8 len2;
410         unsigned char **x = va_arg(ap, unsigned char **);
411         SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
412         HAS_SPACE(src, 1);
413         len2 = (SilcUInt8)src->data[0];
414         silc_buffer_pull(src, 1);
415         HAS_SPACE(src, len2);
416         if (len)
417           *len = len2;
418         if (x && len2) {
419           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
420           memcpy(*x, src->data, len2);
421         }
422         silc_buffer_pull(src, len2);
423         break;
424       }
425     case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
426       {
427         SilcUInt16 len2;
428         unsigned char **x = va_arg(ap, unsigned char **);
429         SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
430         HAS_SPACE(src, 2);
431         SILC_GET16_MSB(len2, src->data);
432         silc_buffer_pull(src, 2);
433         HAS_SPACE(src, len2);
434         if (len)
435           *len = len2;
436         if (x && len2) {
437           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
438           memcpy(*x, src->data, len2);
439         }
440         silc_buffer_pull(src, len2);
441         break;
442       }
443     case SILC_BUFFER_PARAM_UI32_NSTRING:
444       {
445         SilcUInt32 len2;
446         unsigned char **x = va_arg(ap, unsigned char **);
447         SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
448         HAS_SPACE(src, 4);
449         SILC_GET32_MSB(len2, src->data);
450         silc_buffer_pull(src, 4);
451         HAS_SPACE(src, len2);
452         if (len)
453           *len = len2;
454         if (x)
455           *x = src->data;
456         silc_buffer_pull(src, len2);
457         break;
458       }
459     case SILC_BUFFER_PARAM_UI_XNSTRING:
460       {
461         unsigned char **x = va_arg(ap, unsigned char **);
462         SilcUInt32 len = va_arg(ap, SilcUInt32);
463         HAS_SPACE(src, len);
464         if (len && x)
465           *x = src->data;
466         silc_buffer_pull(src, len);
467         break;
468       }
469     case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
470       {
471         unsigned char **x = va_arg(ap, unsigned char **);
472         SilcUInt32 len = va_arg(ap, SilcUInt32);
473         HAS_SPACE(src, len);
474         if (len && x) {
475           *x = silc_calloc(len + 1, sizeof(unsigned char));
476           memcpy(*x, src->data, len);
477         }
478         silc_buffer_pull(src, len);
479         break;
480       }
481     case SILC_BUFFER_PARAM_END:
482       goto ok;
483       break;
484     default:
485       SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
486                       "format the data.", fmt));
487       goto fail;
488       break;
489     }
490   }
491
492  fail:
493   SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
494   return -1;
495
496  ok:
497   /* Push the buffer back to the start. */
498   len = src->data - start_ptr;
499   silc_buffer_push(src, len);
500   return len;
501 }