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 /* Macros 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 FORMAT_HAS_SPACE(__x__, __req__) \
29 if (__req__ > (__x__)->len) \
32 #define UNFORMAT_HAS_SPACE(__x__, __req__) \
34 if (__req__ > (__x__)->len) \
36 if ((__req__ + 1) <= 0) \
40 /* Formats the arguments sent and puts them into the buffer sent as
41 argument. The buffer must be initialized beforehand and it must have
42 enough free space to include the formatted data. If this function
43 fails caller should not trust the buffer anymore and should free it.
44 This function is used, for example, to create packets to send over
47 int silc_buffer_format(SilcBuffer dst, ...)
53 ret = silc_buffer_format_vp(dst, ap);
59 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
61 SilcBufferParamType fmt;
62 unsigned char *start_ptr = dst->data;
65 /* Parse the arguments by formatting type. */
67 fmt = va_arg(ap, SilcBufferParamType);
70 case SILC_BUFFER_PARAM_SI8_CHAR:
72 char x = (char)va_arg(ap, int);
73 FORMAT_HAS_SPACE(dst, 1);
74 silc_buffer_put(dst, &x, 1);
75 silc_buffer_pull(dst, 1);
78 case SILC_BUFFER_PARAM_UI8_CHAR:
80 unsigned char x = (unsigned char)va_arg(ap, int);
81 FORMAT_HAS_SPACE(dst, 1);
82 silc_buffer_put(dst, &x, 1);
83 silc_buffer_pull(dst, 1);
86 case SILC_BUFFER_PARAM_SI16_SHORT:
89 SilcInt16 x = (SilcInt16)va_arg(ap, int);
90 FORMAT_HAS_SPACE(dst, 2);
91 SILC_PUT16_MSB(x, xf);
92 silc_buffer_put(dst, xf, 2);
93 silc_buffer_pull(dst, 2);
96 case SILC_BUFFER_PARAM_UI16_SHORT:
99 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
100 FORMAT_HAS_SPACE(dst, 2);
101 SILC_PUT16_MSB(x, xf);
102 silc_buffer_put(dst, xf, 2);
103 silc_buffer_pull(dst, 2);
106 case SILC_BUFFER_PARAM_SI32_INT:
109 SilcInt32 x = va_arg(ap, SilcInt32);
110 FORMAT_HAS_SPACE(dst, 4);
111 SILC_PUT32_MSB(x, xf);
112 silc_buffer_put(dst, xf, 4);
113 silc_buffer_pull(dst, 4);
116 case SILC_BUFFER_PARAM_UI32_INT:
119 SilcUInt32 x = va_arg(ap, SilcUInt32);
120 FORMAT_HAS_SPACE(dst, 4);
121 SILC_PUT32_MSB(x, xf);
122 silc_buffer_put(dst, xf, 4);
123 silc_buffer_pull(dst, 4);
126 case SILC_BUFFER_PARAM_SI64_INT:
129 SilcInt64 x = va_arg(ap, SilcInt64);
130 FORMAT_HAS_SPACE(dst, sizeof(SilcInt64));
131 SILC_PUT64_MSB(x, xf);
132 silc_buffer_put(dst, xf, sizeof(SilcInt64));
133 silc_buffer_pull(dst, sizeof(SilcInt64));
136 case SILC_BUFFER_PARAM_UI64_INT:
139 SilcUInt64 x = va_arg(ap, SilcUInt64);
140 FORMAT_HAS_SPACE(dst, sizeof(SilcUInt64));
141 SILC_PUT64_MSB(x, xf);
142 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
143 silc_buffer_pull(dst, sizeof(SilcUInt64));
146 case SILC_BUFFER_PARAM_UI8_STRING:
147 case SILC_BUFFER_PARAM_UI16_STRING:
148 case SILC_BUFFER_PARAM_UI32_STRING:
149 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
150 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
151 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
153 unsigned char *x = va_arg(ap, unsigned char *);
154 SilcUInt32 tmp_len = strlen(x);
155 FORMAT_HAS_SPACE(dst, tmp_len);
156 silc_buffer_put(dst, x, tmp_len);
157 silc_buffer_pull(dst, tmp_len);
160 case SILC_BUFFER_PARAM_UI8_NSTRING:
161 case SILC_BUFFER_PARAM_UI16_NSTRING:
162 case SILC_BUFFER_PARAM_UI32_NSTRING:
163 case SILC_BUFFER_PARAM_UI_XNSTRING:
164 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
165 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
166 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
167 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
169 unsigned char *x = va_arg(ap, unsigned char *);
170 SilcUInt32 len = va_arg(ap, SilcUInt32);
172 FORMAT_HAS_SPACE(dst, len);
173 silc_buffer_put(dst, x, len);
174 silc_buffer_pull(dst, len);
178 case SILC_BUFFER_PARAM_END:
182 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
183 "format the data.", fmt));
190 SILC_LOG_DEBUG(("Error occured while formatting data"));
191 len = dst->data - start_ptr;
192 silc_buffer_push(dst, len);
196 /* Push the buffer back to where it belongs. */
197 len = dst->data - start_ptr;
198 silc_buffer_push(dst, len);
202 /* Unformats the buffer sent as argument. The unformatted data is returned
203 to the variable argument list of pointers. The buffer must point to the
204 start of the data area to be unformatted. Buffer maybe be safely free'd
205 after this returns succesfully. */
207 int silc_buffer_unformat(SilcBuffer src, ...)
213 ret = silc_buffer_unformat_vp(src, ap);
219 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
221 SilcBufferParamType fmt;
222 unsigned char *start_ptr = src->data;
225 /* Parse the arguments by formatting type. */
227 fmt = va_arg(ap, SilcBufferParamType);
230 case SILC_BUFFER_PARAM_SI8_CHAR:
232 char *x = va_arg(ap, char *);
233 UNFORMAT_HAS_SPACE(src, 1);
236 silc_buffer_pull(src, 1);
239 case SILC_BUFFER_PARAM_UI8_CHAR:
241 unsigned char *x = va_arg(ap, unsigned char *);
242 UNFORMAT_HAS_SPACE(src, 1);
245 silc_buffer_pull(src, 1);
248 case SILC_BUFFER_PARAM_SI16_SHORT:
250 SilcInt16 *x = va_arg(ap, SilcInt16 *);
251 UNFORMAT_HAS_SPACE(src, 2);
253 SILC_GET16_MSB(*x, src->data);
254 silc_buffer_pull(src, 2);
257 case SILC_BUFFER_PARAM_UI16_SHORT:
259 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
260 UNFORMAT_HAS_SPACE(src, 2);
262 SILC_GET16_MSB(*x, src->data);
263 silc_buffer_pull(src, 2);
266 case SILC_BUFFER_PARAM_SI32_INT:
268 SilcInt32 *x = va_arg(ap, SilcInt32 *);
269 UNFORMAT_HAS_SPACE(src, 4);
271 SILC_GET32_MSB(*x, src->data);
272 silc_buffer_pull(src, 4);
275 case SILC_BUFFER_PARAM_UI32_INT:
277 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
278 UNFORMAT_HAS_SPACE(src, 4);
280 SILC_GET32_MSB(*x, src->data);
281 silc_buffer_pull(src, 4);
284 case SILC_BUFFER_PARAM_SI64_INT:
286 SilcInt64 *x = va_arg(ap, SilcInt64 *);
287 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
289 SILC_GET64_MSB(*x, src->data);
290 silc_buffer_pull(src, sizeof(SilcInt64));
293 case SILC_BUFFER_PARAM_UI64_INT:
295 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
296 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
298 SILC_GET64_MSB(*x, src->data);
299 silc_buffer_pull(src, sizeof(SilcUInt64));
302 case SILC_BUFFER_PARAM_UI8_STRING:
305 unsigned char **x = va_arg(ap, unsigned char **);
306 UNFORMAT_HAS_SPACE(src, 1);
307 len2 = (SilcUInt8)src->data[0];
308 silc_buffer_pull(src, 1);
309 UNFORMAT_HAS_SPACE(src, len2);
312 silc_buffer_pull(src, len2);
315 case SILC_BUFFER_PARAM_UI16_STRING:
318 unsigned char **x = va_arg(ap, unsigned char **);
319 UNFORMAT_HAS_SPACE(src, 2);
320 SILC_GET16_MSB(len2, src->data);
321 silc_buffer_pull(src, 2);
322 UNFORMAT_HAS_SPACE(src, len2);
325 silc_buffer_pull(src, len2);
328 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
331 unsigned char **x = va_arg(ap, unsigned char **);
332 UNFORMAT_HAS_SPACE(src, 1);
333 len2 = (SilcUInt8)src->data[0];
334 silc_buffer_pull(src, 1);
335 UNFORMAT_HAS_SPACE(src, len2);
337 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
338 memcpy(*x, src->data, len2);
340 silc_buffer_pull(src, len2);
343 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
346 unsigned char **x = va_arg(ap, unsigned char **);
347 UNFORMAT_HAS_SPACE(src, 2);
348 SILC_GET16_MSB(len2, src->data);
349 silc_buffer_pull(src, 2);
350 UNFORMAT_HAS_SPACE(src, len2);
352 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
353 memcpy(*x, src->data, len2);
355 silc_buffer_pull(src, len2);
358 case SILC_BUFFER_PARAM_UI32_STRING:
361 unsigned char **x = va_arg(ap, unsigned char **);
362 UNFORMAT_HAS_SPACE(src, 4);
363 SILC_GET32_MSB(len2, src->data);
364 silc_buffer_pull(src, 4);
365 UNFORMAT_HAS_SPACE(src, len2);
368 silc_buffer_pull(src, len2);
371 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
374 unsigned char **x = va_arg(ap, unsigned char **);
375 UNFORMAT_HAS_SPACE(src, 4);
376 SILC_GET32_MSB(len2, src->data);
377 silc_buffer_pull(src, 4);
378 UNFORMAT_HAS_SPACE(src, len2);
380 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
381 memcpy(*x, src->data, len2);
383 silc_buffer_pull(src, len2);
386 case SILC_BUFFER_PARAM_UI8_NSTRING:
389 unsigned char **x = va_arg(ap, unsigned char **);
390 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
391 UNFORMAT_HAS_SPACE(src, 1);
392 len2 = (SilcUInt8)src->data[0];
393 silc_buffer_pull(src, 1);
394 UNFORMAT_HAS_SPACE(src, len2);
399 silc_buffer_pull(src, len2);
402 case SILC_BUFFER_PARAM_UI16_NSTRING:
405 unsigned char **x = va_arg(ap, unsigned char **);
406 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
407 UNFORMAT_HAS_SPACE(src, 2);
408 SILC_GET16_MSB(len2, src->data);
409 silc_buffer_pull(src, 2);
410 UNFORMAT_HAS_SPACE(src, len2);
415 silc_buffer_pull(src, len2);
418 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
421 unsigned char **x = va_arg(ap, unsigned char **);
422 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
423 UNFORMAT_HAS_SPACE(src, 1);
424 len2 = (SilcUInt8)src->data[0];
425 silc_buffer_pull(src, 1);
426 UNFORMAT_HAS_SPACE(src, len2);
430 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
431 memcpy(*x, src->data, len2);
433 silc_buffer_pull(src, len2);
436 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
439 unsigned char **x = va_arg(ap, unsigned char **);
440 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
441 UNFORMAT_HAS_SPACE(src, 2);
442 SILC_GET16_MSB(len2, src->data);
443 silc_buffer_pull(src, 2);
444 UNFORMAT_HAS_SPACE(src, len2);
448 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
449 memcpy(*x, src->data, len2);
451 silc_buffer_pull(src, len2);
454 case SILC_BUFFER_PARAM_UI32_NSTRING:
457 unsigned char **x = va_arg(ap, unsigned char **);
458 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
459 UNFORMAT_HAS_SPACE(src, 4);
460 SILC_GET32_MSB(len2, src->data);
461 silc_buffer_pull(src, 4);
462 UNFORMAT_HAS_SPACE(src, len2);
467 silc_buffer_pull(src, len2);
470 case SILC_BUFFER_PARAM_UI_XNSTRING:
472 unsigned char **x = va_arg(ap, unsigned char **);
473 SilcUInt32 len = va_arg(ap, SilcUInt32);
474 UNFORMAT_HAS_SPACE(src, len);
477 silc_buffer_pull(src, len);
480 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
482 unsigned char **x = va_arg(ap, unsigned char **);
483 SilcUInt32 len = va_arg(ap, SilcUInt32);
484 UNFORMAT_HAS_SPACE(src, len);
486 *x = silc_calloc(len + 1, sizeof(unsigned char));
487 memcpy(*x, src->data, len);
489 silc_buffer_pull(src, len);
492 case SILC_BUFFER_PARAM_END:
496 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
497 "format the data.", fmt));
504 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
505 len = src->data - start_ptr;
506 silc_buffer_push(src, len);
510 /* Push the buffer back to the start. */
511 len = src->data - start_ptr;
512 silc_buffer_push(src, len);
516 /* Formats strings into a buffer */
518 int silc_buffer_strformat(SilcBuffer dst, ...)
520 int len = dst->truelen;
525 /* Parse the arguments by formatting type. */
527 char *string = va_arg(va, char *);
531 if (string == (char *)SILC_BUFFER_PARAM_END)
534 dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
535 (strlen(string) + len + 1));
538 memcpy(dst->head + len, string, strlen(string));
539 len += strlen(string);
540 dst->head[len] = '\0';
543 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
548 dst->end = dst->head + len;
549 dst->data = dst->head;
550 dst->tail = dst->end;
551 dst->len = dst->truelen = len;