Global cosmetic change.
[silc.git] / lib / silccore / 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 /* XXX: These routines needs to be made more stable as these can crash
21    if the data (for unformatting for example) is malformed or the buffer
22    is too short. Must be fixed. There are some other obvious bugs as
23    well. */
24 /*
25  * $Id$
26  * $Log$
27  * Revision 1.2  2000/07/05 06:06:35  priikone
28  *      Global cosmetic change.
29  *
30  * Revision 1.1.1.1  2000/06/27 11:36:55  priikone
31  *      Imported from internal CVS/Added Log headers.
32  *
33  *
34  */
35
36 #include "silcincludes.h"
37
38 /* Formats the arguments sent and puts them into the buffer sent as
39    argument. The buffer must be initialized beforehand and it must have
40    enough free space to include the formatted data. If this function
41    fails caller should not trust the buffer anymore and should free it. 
42    This function is used, for example, to create packets to send over
43    network. */
44
45 int silc_buffer_format(SilcBuffer dst, ...)
46 {
47   va_list ap;
48   SilcBufferParamType fmt;
49   unsigned char *start_ptr = dst->data;
50
51   va_start(ap, dst);
52
53   /* Parse the arguments by formatting type. */
54   while(1) {
55     fmt = va_arg(ap, SilcBufferParamType);
56
57     switch(fmt) {
58     case SILC_BUFFER_PARAM_SI8_CHAR:
59       {
60         char x = va_arg(ap, char);
61         silc_buffer_put(dst, &x, 1);
62         silc_buffer_pull(dst, 1);
63         break;
64       }
65     case SILC_BUFFER_PARAM_UI8_CHAR:
66       {
67         unsigned char x = va_arg(ap, unsigned char);
68         silc_buffer_put(dst, &x, 1);
69         silc_buffer_pull(dst, 1);
70         break;
71       }
72     case SILC_BUFFER_PARAM_SI16_SHORT:
73       {
74         unsigned char xf[2];
75         short x = va_arg(ap, short);
76         SILC_PUT16_MSB(x, xf);
77         silc_buffer_put(dst, xf, 2);
78         silc_buffer_pull(dst, 2);
79         break;
80       }
81     case SILC_BUFFER_PARAM_UI16_SHORT:
82       {
83         unsigned char xf[2];
84         unsigned short x = va_arg(ap, unsigned short);
85         SILC_PUT16_MSB(x, xf);
86         silc_buffer_put(dst, xf, 2);
87         silc_buffer_pull(dst, 2);
88         break;
89       }
90     case SILC_BUFFER_PARAM_SI32_INT:
91       {
92         unsigned char xf[4];
93         int x = va_arg(ap, int);
94         SILC_PUT32_MSB(x, xf);
95         silc_buffer_put(dst, xf, 4);
96         silc_buffer_pull(dst, 4);
97         break;
98       }
99     case SILC_BUFFER_PARAM_UI32_INT:
100       {
101         unsigned char xf[4];
102         unsigned int x = va_arg(ap, unsigned int);
103         SILC_PUT32_MSB(x, xf);
104         silc_buffer_put(dst, xf, 4);
105         silc_buffer_pull(dst, 4);
106         break;
107       }
108     case SILC_BUFFER_PARAM_UI16_STRING:
109     case SILC_BUFFER_PARAM_UI32_STRING:
110     case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
111     case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
112       {
113         unsigned char *x = va_arg(ap, unsigned char *);
114         silc_buffer_put(dst, x, strlen(x));
115         silc_buffer_pull(dst, strlen(x));
116         break;
117       }
118     case SILC_BUFFER_PARAM_UI16_NSTRING:
119     case SILC_BUFFER_PARAM_UI32_NSTRING:
120     case SILC_BUFFER_PARAM_UI_XNSTRING:
121     case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
122     case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
123     case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
124       {
125         unsigned char *x = va_arg(ap, unsigned char *);
126         unsigned int len = va_arg(ap, unsigned int);
127         silc_buffer_put(dst, x, len);
128         silc_buffer_pull(dst, len);
129         break;
130       }
131     case SILC_BUFFER_PARAM_END:
132       goto ok;
133       break;
134     default:
135       SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
136                       "format the data.", fmt));
137       goto fail;
138       break;
139     }
140   }
141
142  fail:
143   SILC_LOG_ERROR(("Error occured while formatting data"));
144   return FALSE;
145
146  ok:
147   /* Push the buffer back to where it belongs. */
148   silc_buffer_push(dst, dst->data - start_ptr);
149   return dst->len;
150 }
151
152 /* Unformats the buffer sent as argument. The unformatted data is returned
153    to the variable argument list of pointers. The buffer must point to the
154    start of the data area to be unformatted. Buffer maybe be safely free'd
155    after this returns succesfully. */
156
157 int silc_buffer_unformat(SilcBuffer src, ...)
158 {
159   va_list ap;
160   SilcBufferParamType fmt;
161   unsigned char *start_ptr = src->data;
162   int len = 0;
163
164   va_start(ap, src);
165
166   /* Parse the arguments by formatting type. */
167   while(1) {
168     fmt = va_arg(ap, SilcBufferParamType);
169
170     switch(fmt) {
171     case SILC_BUFFER_PARAM_SI8_CHAR:
172       {
173         char *x = va_arg(ap, char *);
174         if (x)
175           *x = src->data[0];
176         silc_buffer_pull(src, 1);
177         break;
178       }
179     case SILC_BUFFER_PARAM_UI8_CHAR:
180       {
181         unsigned char *x = va_arg(ap, unsigned char *);
182         if (x)
183           *x = src->data[0];
184         silc_buffer_pull(src, 1);
185         break;
186       }
187     case SILC_BUFFER_PARAM_SI16_SHORT:
188       {
189         short *x = va_arg(ap, short *);
190         if (x)
191           SILC_GET16_MSB(*x, src->data);
192         silc_buffer_pull(src, 2);
193         break;
194       }
195     case SILC_BUFFER_PARAM_UI16_SHORT:
196       {
197         unsigned short *x = va_arg(ap, unsigned short *);
198         if (x)
199           SILC_GET16_MSB(*x, src->data);
200         silc_buffer_pull(src, 2);
201         break;
202       }
203     case SILC_BUFFER_PARAM_SI32_INT:
204       {
205         int *x = va_arg(ap, int *);
206         if (x)
207           SILC_GET32_MSB(*x, src->data);
208         silc_buffer_pull(src, 4);
209         break;
210       }
211     case SILC_BUFFER_PARAM_UI32_INT:
212       {
213         unsigned int *x = va_arg(ap, unsigned int *);
214         if (x)
215           SILC_GET32_MSB(*x, src->data);
216         silc_buffer_pull(src, 4);
217         break;
218       }
219     case SILC_BUFFER_PARAM_UI16_STRING:
220       {
221         unsigned short len2;
222         unsigned char **x = va_arg(ap, unsigned char **);
223         SILC_GET16_MSB(len2, src->data);
224         silc_buffer_pull(src, 2);
225         if ((len2 > src->len))
226           goto fail;
227         if (len2 < 1)
228           break;
229         if (x)
230           memcpy(x, src->data, len2);
231         silc_buffer_pull(src, len2);
232         break;
233       }
234     case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
235       {
236         unsigned short len2;
237         unsigned char **x = va_arg(ap, unsigned char **);
238         SILC_GET16_MSB(len2, src->data);
239         silc_buffer_pull(src, 2);
240         if ((len2 > src->len))
241           goto fail;
242         if (len2 < 1)
243           break;
244         if (x) {
245           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
246           memcpy(*x, src->data, len2);
247         }
248         silc_buffer_pull(src, len2);
249         break;
250       }
251     case SILC_BUFFER_PARAM_UI32_STRING:
252       {
253         unsigned int len2;
254         unsigned char **x = va_arg(ap, unsigned char **);
255         SILC_GET32_MSB(len2, src->data);
256         silc_buffer_pull(src, 4);
257         if ((len2 > src->len))
258           goto fail;
259         if (len2 < 1)
260           break;
261         if (x)
262           memcpy(x, src->data, len2);
263         silc_buffer_pull(src, len2);
264         break;
265       }
266     case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
267       {
268         unsigned int len2;
269         unsigned char **x = va_arg(ap, unsigned char **);
270         SILC_GET32_MSB(len2, src->data);
271         silc_buffer_pull(src, 4);
272         if ((len2 > src->len))
273           goto fail;
274         if (len2 < 1)
275           break;
276         if (x) {
277           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
278           memcpy(*x, src->data, len2);
279         }
280         silc_buffer_pull(src, len2);
281         break;
282       }
283     case SILC_BUFFER_PARAM_UI16_NSTRING:
284       {
285         unsigned short len2;
286         unsigned char **x = va_arg(ap, unsigned char **);
287         unsigned short *len = va_arg(ap, unsigned short *);
288         SILC_GET16_MSB(len2, src->data);
289         silc_buffer_pull(src, 2);
290         if ((len2 > src->len))
291           break;
292         if (len2 < 1)
293           break;
294         if (len)
295           *len = len2;
296         if (x)
297           memcpy(x, src->data, len2);
298         silc_buffer_pull(src, len2);
299         break;
300       }
301     case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
302       {
303         unsigned short len2;
304         unsigned char **x = va_arg(ap, unsigned char **);
305         unsigned short *len = va_arg(ap, unsigned short *);
306         SILC_GET16_MSB(len2, src->data);
307         silc_buffer_pull(src, 2);
308         if ((len2 > src->len))
309           break;
310         if (len2 < 1)
311           break;
312         if (len)
313           *len = len2;
314         if (x) {
315           *x = silc_calloc(len2 + 1, sizeof(unsigned char));
316           memcpy(*x, src->data, len2);
317         }
318         silc_buffer_pull(src, len2);
319         break;
320       }
321     case SILC_BUFFER_PARAM_UI32_NSTRING:
322       {
323         unsigned int len2;
324         unsigned char **x = va_arg(ap, unsigned char **);
325         unsigned int *len = va_arg(ap, unsigned int *);
326         SILC_GET32_MSB(len2, src->data);
327         silc_buffer_pull(src, 4);
328         if ((len2 > src->len))
329           goto fail;
330         if (len2 < 1)
331           break;
332         if (len)
333           *len = len2;
334         if (x)
335           memcpy(x, src->data, len2);
336         silc_buffer_pull(src, len2);
337         break;
338       }
339     case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
340       {
341         unsigned char **x = va_arg(ap, unsigned char **);
342         unsigned int len = va_arg(ap, unsigned int);
343         if (len && x) {
344           *x = silc_calloc(len + 1, sizeof(unsigned char));
345           memcpy(*x, src->data, len);
346         }
347         silc_buffer_pull(src, len);
348         break;
349       }
350     case SILC_BUFFER_PARAM_UI_XNSTRING:
351       {
352         unsigned char **x = va_arg(ap, unsigned char **);
353         unsigned int len = va_arg(ap, unsigned int);
354         if (len && x)
355           memcpy(x, src->data, len);
356         silc_buffer_pull(src, len);
357         break;
358       }
359     case SILC_BUFFER_PARAM_END:
360       goto ok;
361       break;
362     default:
363       SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
364                       "format the data.", fmt));
365       goto fail;
366       break;
367     }
368   }
369
370  fail:
371   SILC_LOG_ERROR(("Error occured while unformatting buffer"));
372   return FALSE;
373
374  ok:
375   /* Push the buffer back to the start. */
376   len = src->data - start_ptr;
377   silc_buffer_push(src, len);
378   return len;
379 }