5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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; either version 2 of the License, or
12 (at your option) any later version.
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.
22 #include "silcincludes.h"
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) \
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
40 int silc_buffer_format(SilcBuffer dst, ...)
43 SilcBufferParamType fmt;
44 unsigned char *start_ptr = dst->data;
48 /* Parse the arguments by formatting type. */
50 fmt = va_arg(ap, SilcBufferParamType);
53 case SILC_BUFFER_PARAM_SI8_CHAR:
55 char x = (char)va_arg(ap, int);
57 silc_buffer_put(dst, &x, 1);
58 silc_buffer_pull(dst, 1);
61 case SILC_BUFFER_PARAM_UI8_CHAR:
63 unsigned char x = (unsigned char)va_arg(ap, int);
65 silc_buffer_put(dst, &x, 1);
66 silc_buffer_pull(dst, 1);
69 case SILC_BUFFER_PARAM_SI16_SHORT:
72 short x = (short)va_arg(ap, int);
74 SILC_PUT16_MSB(x, xf);
75 silc_buffer_put(dst, xf, 2);
76 silc_buffer_pull(dst, 2);
79 case SILC_BUFFER_PARAM_UI16_SHORT:
82 unsigned short x = (unsigned short)va_arg(ap, int);
84 SILC_PUT16_MSB(x, xf);
85 silc_buffer_put(dst, xf, 2);
86 silc_buffer_pull(dst, 2);
89 case SILC_BUFFER_PARAM_SI32_INT:
92 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);
99 case SILC_BUFFER_PARAM_UI32_INT:
102 unsigned int x = va_arg(ap, unsigned int);
104 SILC_PUT32_MSB(x, xf);
105 silc_buffer_put(dst, xf, 4);
106 silc_buffer_pull(dst, 4);
109 case SILC_BUFFER_PARAM_UI16_STRING:
110 case SILC_BUFFER_PARAM_UI32_STRING:
111 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
112 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
114 unsigned char *x = va_arg(ap, unsigned char *);
115 int tmp_len = strlen(x);
116 HAS_SPACE(dst, tmp_len);
117 silc_buffer_put(dst, x, tmp_len);
118 silc_buffer_pull(dst, tmp_len);
121 case SILC_BUFFER_PARAM_UI16_NSTRING:
122 case SILC_BUFFER_PARAM_UI32_NSTRING:
123 case SILC_BUFFER_PARAM_UI_XNSTRING:
124 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
125 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
126 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
128 unsigned char *x = va_arg(ap, unsigned char *);
129 unsigned int len = va_arg(ap, unsigned int);
131 silc_buffer_put(dst, x, len);
132 silc_buffer_pull(dst, len);
135 case SILC_BUFFER_PARAM_END:
139 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
140 "format the data.", fmt));
147 SILC_LOG_DEBUG(("Error occured while formatting data"));
154 /* Push the buffer back to where it belongs. */
155 silc_buffer_push(dst, dst->data - start_ptr);
159 /* Unformats the buffer sent as argument. The unformatted data is returned
160 to the variable argument list of pointers. The buffer must point to the
161 start of the data area to be unformatted. Buffer maybe be safely free'd
162 after this returns succesfully. */
164 int silc_buffer_unformat(SilcBuffer src, ...)
167 SilcBufferParamType fmt;
168 unsigned char *start_ptr = src->data;
173 /* Parse the arguments by formatting type. */
175 fmt = va_arg(ap, SilcBufferParamType);
178 case SILC_BUFFER_PARAM_SI8_CHAR:
180 char *x = va_arg(ap, char *);
184 silc_buffer_pull(src, 1);
187 case SILC_BUFFER_PARAM_UI8_CHAR:
189 unsigned char *x = va_arg(ap, unsigned char *);
193 silc_buffer_pull(src, 1);
196 case SILC_BUFFER_PARAM_SI16_SHORT:
198 short *x = va_arg(ap, short *);
201 SILC_GET16_MSB(*x, src->data);
202 silc_buffer_pull(src, 2);
205 case SILC_BUFFER_PARAM_UI16_SHORT:
207 unsigned short *x = va_arg(ap, unsigned short *);
210 SILC_GET16_MSB(*x, src->data);
211 silc_buffer_pull(src, 2);
214 case SILC_BUFFER_PARAM_SI32_INT:
216 int *x = va_arg(ap, int *);
219 SILC_GET32_MSB(*x, src->data);
220 silc_buffer_pull(src, 4);
223 case SILC_BUFFER_PARAM_UI32_INT:
225 unsigned int *x = va_arg(ap, unsigned int *);
228 SILC_GET32_MSB(*x, src->data);
229 silc_buffer_pull(src, 4);
232 case SILC_BUFFER_PARAM_UI16_STRING:
235 unsigned char **x = va_arg(ap, unsigned char **);
237 SILC_GET16_MSB(len2, src->data);
238 silc_buffer_pull(src, 2);
239 HAS_SPACE(src, len2);
242 silc_buffer_pull(src, len2);
245 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
248 unsigned char **x = va_arg(ap, unsigned char **);
250 SILC_GET16_MSB(len2, src->data);
251 silc_buffer_pull(src, 2);
252 HAS_SPACE(src, len2);
254 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
255 memcpy(*x, src->data, len2);
257 silc_buffer_pull(src, len2);
260 case SILC_BUFFER_PARAM_UI32_STRING:
263 unsigned char **x = va_arg(ap, unsigned char **);
265 SILC_GET32_MSB(len2, src->data);
266 silc_buffer_pull(src, 4);
267 HAS_SPACE(src, len2);
270 silc_buffer_pull(src, len2);
273 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
276 unsigned char **x = va_arg(ap, unsigned char **);
278 SILC_GET32_MSB(len2, src->data);
279 silc_buffer_pull(src, 4);
280 HAS_SPACE(src, len2);
282 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
283 memcpy(*x, src->data, len2);
285 silc_buffer_pull(src, len2);
288 case SILC_BUFFER_PARAM_UI16_NSTRING:
291 unsigned char **x = va_arg(ap, unsigned char **);
292 unsigned short *len = va_arg(ap, unsigned short *);
294 SILC_GET16_MSB(len2, src->data);
295 silc_buffer_pull(src, 2);
296 HAS_SPACE(src, len2);
301 silc_buffer_pull(src, len2);
304 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
307 unsigned char **x = va_arg(ap, unsigned char **);
308 unsigned short *len = va_arg(ap, unsigned short *);
310 SILC_GET16_MSB(len2, src->data);
311 silc_buffer_pull(src, 2);
312 HAS_SPACE(src, len2);
316 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
317 memcpy(*x, src->data, len2);
319 silc_buffer_pull(src, len2);
322 case SILC_BUFFER_PARAM_UI32_NSTRING:
325 unsigned char **x = va_arg(ap, unsigned char **);
326 unsigned int *len = va_arg(ap, unsigned int *);
328 SILC_GET32_MSB(len2, src->data);
329 silc_buffer_pull(src, 4);
330 HAS_SPACE(src, len2);
335 silc_buffer_pull(src, len2);
338 case SILC_BUFFER_PARAM_UI_XNSTRING:
340 unsigned char **x = va_arg(ap, unsigned char **);
341 unsigned int len = va_arg(ap, unsigned int);
345 silc_buffer_pull(src, len);
348 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
350 unsigned char **x = va_arg(ap, unsigned char **);
351 unsigned int len = va_arg(ap, unsigned int);
354 *x = silc_calloc(len + 1, sizeof(unsigned char));
355 memcpy(*x, src->data, len);
357 silc_buffer_pull(src, len);
360 case SILC_BUFFER_PARAM_END:
364 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
365 "format the data.", fmt));
372 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
379 /* Push the buffer back to the start. */
380 len = src->data - start_ptr;
381 silc_buffer_push(src, len);