5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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 MY_HAS_SPACE(__x__, __req__) \
29 if (__req__ > (__x__)->len) \
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, ...)
46 ret = silc_buffer_format_vp(dst, ap);
52 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
54 SilcBufferParamType fmt;
55 unsigned char *start_ptr = dst->data;
58 /* Parse the arguments by formatting type. */
60 fmt = va_arg(ap, SilcBufferParamType);
63 case SILC_BUFFER_PARAM_SI8_CHAR:
65 char x = (char)va_arg(ap, int);
67 silc_buffer_put(dst, &x, 1);
68 silc_buffer_pull(dst, 1);
71 case SILC_BUFFER_PARAM_UI8_CHAR:
73 unsigned char x = (unsigned char)va_arg(ap, int);
75 silc_buffer_put(dst, &x, 1);
76 silc_buffer_pull(dst, 1);
79 case SILC_BUFFER_PARAM_SI16_SHORT:
82 SilcInt16 x = (SilcInt16)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_UI16_SHORT:
92 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
94 SILC_PUT16_MSB(x, xf);
95 silc_buffer_put(dst, xf, 2);
96 silc_buffer_pull(dst, 2);
99 case SILC_BUFFER_PARAM_SI32_INT:
102 SilcInt32 x = va_arg(ap, SilcInt32);
103 MY_HAS_SPACE(dst, 4);
104 SILC_PUT32_MSB(x, xf);
105 silc_buffer_put(dst, xf, 4);
106 silc_buffer_pull(dst, 4);
109 case SILC_BUFFER_PARAM_UI32_INT:
112 SilcUInt32 x = va_arg(ap, SilcUInt32);
113 MY_HAS_SPACE(dst, 4);
114 SILC_PUT32_MSB(x, xf);
115 silc_buffer_put(dst, xf, 4);
116 silc_buffer_pull(dst, 4);
119 case SILC_BUFFER_PARAM_SI64_INT:
122 SilcInt64 x = va_arg(ap, SilcInt64);
123 MY_HAS_SPACE(dst, sizeof(SilcInt64));
124 SILC_PUT64_MSB(x, xf);
125 silc_buffer_put(dst, xf, sizeof(SilcInt64));
126 silc_buffer_pull(dst, sizeof(SilcInt64));
129 case SILC_BUFFER_PARAM_UI64_INT:
132 SilcUInt64 x = va_arg(ap, SilcUInt64);
133 MY_HAS_SPACE(dst, sizeof(SilcUInt64));
134 SILC_PUT64_MSB(x, xf);
135 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
136 silc_buffer_pull(dst, sizeof(SilcUInt64));
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:
146 unsigned char *x = va_arg(ap, unsigned char *);
147 SilcUInt32 tmp_len = strlen(x);
148 MY_HAS_SPACE(dst, tmp_len);
149 silc_buffer_put(dst, x, tmp_len);
150 silc_buffer_pull(dst, tmp_len);
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:
162 unsigned char *x = va_arg(ap, unsigned char *);
163 SilcUInt32 len = va_arg(ap, SilcUInt32);
164 MY_HAS_SPACE(dst, len);
165 silc_buffer_put(dst, x, len);
166 silc_buffer_pull(dst, len);
169 case SILC_BUFFER_PARAM_END:
173 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
174 "format the data.", fmt));
181 SILC_LOG_DEBUG(("Error occured while formatting data"));
185 /* Push the buffer back to where it belongs. */
186 len = dst->data - start_ptr;
187 silc_buffer_push(dst, len);
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. */
196 int silc_buffer_unformat(SilcBuffer src, ...)
202 ret = silc_buffer_unformat_vp(src, ap);
208 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
210 SilcBufferParamType fmt;
211 unsigned char *start_ptr = src->data;
214 /* Parse the arguments by formatting type. */
216 fmt = va_arg(ap, SilcBufferParamType);
219 case SILC_BUFFER_PARAM_SI8_CHAR:
221 char *x = va_arg(ap, char *);
222 MY_HAS_SPACE(src, 1);
225 silc_buffer_pull(src, 1);
228 case SILC_BUFFER_PARAM_UI8_CHAR:
230 unsigned char *x = va_arg(ap, unsigned char *);
231 MY_HAS_SPACE(src, 1);
234 silc_buffer_pull(src, 1);
237 case SILC_BUFFER_PARAM_SI16_SHORT:
239 SilcInt16 *x = va_arg(ap, SilcInt16 *);
240 MY_HAS_SPACE(src, 2);
242 SILC_GET16_MSB(*x, src->data);
243 silc_buffer_pull(src, 2);
246 case SILC_BUFFER_PARAM_UI16_SHORT:
248 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
249 MY_HAS_SPACE(src, 2);
251 SILC_GET16_MSB(*x, src->data);
252 silc_buffer_pull(src, 2);
255 case SILC_BUFFER_PARAM_SI32_INT:
257 SilcInt32 *x = va_arg(ap, SilcInt32 *);
258 MY_HAS_SPACE(src, 4);
260 SILC_GET32_MSB(*x, src->data);
261 silc_buffer_pull(src, 4);
264 case SILC_BUFFER_PARAM_UI32_INT:
266 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
267 MY_HAS_SPACE(src, 4);
269 SILC_GET32_MSB(*x, src->data);
270 silc_buffer_pull(src, 4);
273 case SILC_BUFFER_PARAM_SI64_INT:
275 SilcInt64 *x = va_arg(ap, SilcInt64 *);
276 MY_HAS_SPACE(src, sizeof(SilcInt64));
278 SILC_GET64_MSB(*x, src->data);
279 silc_buffer_pull(src, sizeof(SilcInt64));
282 case SILC_BUFFER_PARAM_UI64_INT:
284 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
285 MY_HAS_SPACE(src, sizeof(SilcUInt64));
287 SILC_GET64_MSB(*x, src->data);
288 silc_buffer_pull(src, sizeof(SilcUInt64));
291 case SILC_BUFFER_PARAM_UI8_STRING:
294 unsigned char **x = va_arg(ap, unsigned char **);
295 MY_HAS_SPACE(src, 1);
296 len2 = (SilcUInt8)src->data[0];
297 silc_buffer_pull(src, 1);
298 MY_HAS_SPACE(src, len2);
301 silc_buffer_pull(src, len2);
304 case SILC_BUFFER_PARAM_UI16_STRING:
307 unsigned char **x = va_arg(ap, unsigned char **);
308 MY_HAS_SPACE(src, 2);
309 SILC_GET16_MSB(len2, src->data);
310 silc_buffer_pull(src, 2);
311 MY_HAS_SPACE(src, len2);
314 silc_buffer_pull(src, len2);
317 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
320 unsigned char **x = va_arg(ap, unsigned char **);
321 MY_HAS_SPACE(src, 1);
322 len2 = (SilcUInt8)src->data[0];
323 silc_buffer_pull(src, 1);
324 MY_HAS_SPACE(src, len2);
326 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
327 memcpy(*x, src->data, len2);
329 silc_buffer_pull(src, len2);
332 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
335 unsigned char **x = va_arg(ap, unsigned char **);
336 MY_HAS_SPACE(src, 2);
337 SILC_GET16_MSB(len2, src->data);
338 silc_buffer_pull(src, 2);
339 MY_HAS_SPACE(src, len2);
341 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
342 memcpy(*x, src->data, len2);
344 silc_buffer_pull(src, len2);
347 case SILC_BUFFER_PARAM_UI32_STRING:
350 unsigned char **x = va_arg(ap, unsigned char **);
351 MY_HAS_SPACE(src, 4);
352 SILC_GET32_MSB(len2, src->data);
353 silc_buffer_pull(src, 4);
354 MY_HAS_SPACE(src, len2);
357 silc_buffer_pull(src, len2);
360 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
363 unsigned char **x = va_arg(ap, unsigned char **);
364 MY_HAS_SPACE(src, 4);
365 SILC_GET32_MSB(len2, src->data);
366 silc_buffer_pull(src, 4);
367 MY_HAS_SPACE(src, len2);
369 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
370 memcpy(*x, src->data, len2);
372 silc_buffer_pull(src, len2);
375 case SILC_BUFFER_PARAM_UI8_NSTRING:
378 unsigned char **x = va_arg(ap, unsigned char **);
379 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
380 MY_HAS_SPACE(src, 1);
381 len2 = (SilcUInt8)src->data[0];
382 silc_buffer_pull(src, 1);
383 MY_HAS_SPACE(src, len2);
388 silc_buffer_pull(src, len2);
391 case SILC_BUFFER_PARAM_UI16_NSTRING:
394 unsigned char **x = va_arg(ap, unsigned char **);
395 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
396 MY_HAS_SPACE(src, 2);
397 SILC_GET16_MSB(len2, src->data);
398 silc_buffer_pull(src, 2);
399 MY_HAS_SPACE(src, len2);
404 silc_buffer_pull(src, len2);
407 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
410 unsigned char **x = va_arg(ap, unsigned char **);
411 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
412 MY_HAS_SPACE(src, 1);
413 len2 = (SilcUInt8)src->data[0];
414 silc_buffer_pull(src, 1);
415 MY_HAS_SPACE(src, len2);
419 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
420 memcpy(*x, src->data, len2);
422 silc_buffer_pull(src, len2);
425 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
428 unsigned char **x = va_arg(ap, unsigned char **);
429 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
430 MY_HAS_SPACE(src, 2);
431 SILC_GET16_MSB(len2, src->data);
432 silc_buffer_pull(src, 2);
433 MY_HAS_SPACE(src, len2);
437 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
438 memcpy(*x, src->data, len2);
440 silc_buffer_pull(src, len2);
443 case SILC_BUFFER_PARAM_UI32_NSTRING:
446 unsigned char **x = va_arg(ap, unsigned char **);
447 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
448 MY_HAS_SPACE(src, 4);
449 SILC_GET32_MSB(len2, src->data);
450 silc_buffer_pull(src, 4);
451 MY_HAS_SPACE(src, len2);
456 silc_buffer_pull(src, len2);
459 case SILC_BUFFER_PARAM_UI_XNSTRING:
461 unsigned char **x = va_arg(ap, unsigned char **);
462 SilcUInt32 len = va_arg(ap, SilcUInt32);
463 MY_HAS_SPACE(src, len);
466 silc_buffer_pull(src, len);
469 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
471 unsigned char **x = va_arg(ap, unsigned char **);
472 SilcUInt32 len = va_arg(ap, SilcUInt32);
473 MY_HAS_SPACE(src, len);
475 *x = silc_calloc(len + 1, sizeof(unsigned char));
476 memcpy(*x, src->data, len);
478 silc_buffer_pull(src, len);
481 case SILC_BUFFER_PARAM_END:
485 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
486 "format the data.", fmt));
493 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
497 /* Push the buffer back to the start. */
498 len = src->data - start_ptr;
499 silc_buffer_push(src, len);
503 /* Formats strings into a buffer */
505 int silc_buffer_strformat(SilcBuffer dst, ...)
507 int len = dst->truelen;
512 /* Parse the arguments by formatting type. */
514 char *string = va_arg(va, char *);
518 if (string == (char *)SILC_BUFFER_PARAM_END)
521 dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
522 (strlen(string) + len));
523 memcpy(dst->head + len, string, strlen(string));
524 len += strlen(string);
527 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
532 dst->end = dst->head + len;
533 dst->tail = dst->data = dst->end;