5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "silcincludes.h"
23 /* Macros to check whether there is enough free space to add the
24 required amount of data. For unformatting this means that there must
25 be the data that is to be extracted. */
26 #define FORMAT_HAS_SPACE(__x__, __req__) \
28 if (__req__ > (__x__)->len) \
31 #define UNFORMAT_HAS_SPACE(__x__, __req__) \
33 if (__req__ > (__x__)->len) \
35 if ((__req__ + 1) <= 0) \
39 /* Formats the arguments sent and puts them into the buffer sent as
40 argument. The buffer must be initialized beforehand and it must have
41 enough free space to include the formatted data. If this function
42 fails caller should not trust the buffer anymore and should free it.
43 This function is used, for example, to create packets to send over
46 int silc_buffer_format(SilcBuffer dst, ...)
52 ret = silc_buffer_format_vp(dst, ap);
58 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
60 SilcBufferParamType fmt;
61 unsigned char *start_ptr = dst->data;
64 /* Parse the arguments by formatting type. */
66 fmt = va_arg(ap, SilcBufferParamType);
69 case SILC_BUFFER_PARAM_SI8_CHAR:
71 char x = (char)va_arg(ap, int);
72 FORMAT_HAS_SPACE(dst, 1);
73 silc_buffer_put(dst, &x, 1);
74 silc_buffer_pull(dst, 1);
77 case SILC_BUFFER_PARAM_UI8_CHAR:
79 unsigned char x = (unsigned char)va_arg(ap, int);
80 FORMAT_HAS_SPACE(dst, 1);
81 silc_buffer_put(dst, &x, 1);
82 silc_buffer_pull(dst, 1);
85 case SILC_BUFFER_PARAM_SI16_SHORT:
88 SilcInt16 x = (SilcInt16)va_arg(ap, int);
89 FORMAT_HAS_SPACE(dst, 2);
90 SILC_PUT16_MSB(x, xf);
91 silc_buffer_put(dst, xf, 2);
92 silc_buffer_pull(dst, 2);
95 case SILC_BUFFER_PARAM_UI16_SHORT:
98 SilcUInt16 x = (SilcUInt16)va_arg(ap, int);
99 FORMAT_HAS_SPACE(dst, 2);
100 SILC_PUT16_MSB(x, xf);
101 silc_buffer_put(dst, xf, 2);
102 silc_buffer_pull(dst, 2);
105 case SILC_BUFFER_PARAM_SI32_INT:
108 SilcInt32 x = va_arg(ap, SilcInt32);
109 FORMAT_HAS_SPACE(dst, 4);
110 SILC_PUT32_MSB(x, xf);
111 silc_buffer_put(dst, xf, 4);
112 silc_buffer_pull(dst, 4);
115 case SILC_BUFFER_PARAM_UI32_INT:
118 SilcUInt32 x = va_arg(ap, SilcUInt32);
119 FORMAT_HAS_SPACE(dst, 4);
120 SILC_PUT32_MSB(x, xf);
121 silc_buffer_put(dst, xf, 4);
122 silc_buffer_pull(dst, 4);
125 case SILC_BUFFER_PARAM_SI64_INT:
128 SilcInt64 x = va_arg(ap, SilcInt64);
129 FORMAT_HAS_SPACE(dst, sizeof(SilcInt64));
130 SILC_PUT64_MSB(x, xf);
131 silc_buffer_put(dst, xf, sizeof(SilcInt64));
132 silc_buffer_pull(dst, sizeof(SilcInt64));
135 case SILC_BUFFER_PARAM_UI64_INT:
138 SilcUInt64 x = va_arg(ap, SilcUInt64);
139 FORMAT_HAS_SPACE(dst, sizeof(SilcUInt64));
140 SILC_PUT64_MSB(x, xf);
141 silc_buffer_put(dst, xf, sizeof(SilcUInt64));
142 silc_buffer_pull(dst, sizeof(SilcUInt64));
145 case SILC_BUFFER_PARAM_UI8_STRING:
146 case SILC_BUFFER_PARAM_UI16_STRING:
147 case SILC_BUFFER_PARAM_UI32_STRING:
148 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
149 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
150 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
152 unsigned char *x = va_arg(ap, unsigned char *);
153 SilcUInt32 tmp_len = strlen(x);
154 FORMAT_HAS_SPACE(dst, tmp_len);
155 silc_buffer_put(dst, x, tmp_len);
156 silc_buffer_pull(dst, tmp_len);
159 case SILC_BUFFER_PARAM_UI8_NSTRING:
160 case SILC_BUFFER_PARAM_UI16_NSTRING:
161 case SILC_BUFFER_PARAM_UI32_NSTRING:
162 case SILC_BUFFER_PARAM_UI_XNSTRING:
163 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
164 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
165 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
166 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
168 unsigned char *x = va_arg(ap, unsigned char *);
169 SilcUInt32 len = va_arg(ap, SilcUInt32);
171 FORMAT_HAS_SPACE(dst, len);
172 silc_buffer_put(dst, x, len);
173 silc_buffer_pull(dst, len);
177 case SILC_BUFFER_PARAM_END:
181 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
182 "format the data.", fmt));
189 SILC_LOG_DEBUG(("Error occured while formatting data"));
190 len = dst->data - start_ptr;
191 silc_buffer_push(dst, len);
195 /* Push the buffer back to where it belongs. */
196 len = dst->data - start_ptr;
197 silc_buffer_push(dst, len);
201 /* Unformats the buffer sent as argument. The unformatted data is returned
202 to the variable argument list of pointers. The buffer must point to the
203 start of the data area to be unformatted. Buffer maybe be safely free'd
204 after this returns succesfully. */
206 int silc_buffer_unformat(SilcBuffer src, ...)
212 ret = silc_buffer_unformat_vp(src, ap);
218 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
220 SilcBufferParamType fmt;
221 unsigned char *start_ptr = src->data;
224 /* Parse the arguments by formatting type. */
226 fmt = va_arg(ap, SilcBufferParamType);
229 case SILC_BUFFER_PARAM_SI8_CHAR:
231 char *x = va_arg(ap, char *);
232 UNFORMAT_HAS_SPACE(src, 1);
235 silc_buffer_pull(src, 1);
238 case SILC_BUFFER_PARAM_UI8_CHAR:
240 unsigned char *x = va_arg(ap, unsigned char *);
241 UNFORMAT_HAS_SPACE(src, 1);
244 silc_buffer_pull(src, 1);
247 case SILC_BUFFER_PARAM_SI16_SHORT:
249 SilcInt16 *x = va_arg(ap, SilcInt16 *);
250 UNFORMAT_HAS_SPACE(src, 2);
252 SILC_GET16_MSB(*x, src->data);
253 silc_buffer_pull(src, 2);
256 case SILC_BUFFER_PARAM_UI16_SHORT:
258 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
259 UNFORMAT_HAS_SPACE(src, 2);
261 SILC_GET16_MSB(*x, src->data);
262 silc_buffer_pull(src, 2);
265 case SILC_BUFFER_PARAM_SI32_INT:
267 SilcInt32 *x = va_arg(ap, SilcInt32 *);
268 UNFORMAT_HAS_SPACE(src, 4);
270 SILC_GET32_MSB(*x, src->data);
271 silc_buffer_pull(src, 4);
274 case SILC_BUFFER_PARAM_UI32_INT:
276 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
277 UNFORMAT_HAS_SPACE(src, 4);
279 SILC_GET32_MSB(*x, src->data);
280 silc_buffer_pull(src, 4);
283 case SILC_BUFFER_PARAM_SI64_INT:
285 SilcInt64 *x = va_arg(ap, SilcInt64 *);
286 UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
288 SILC_GET64_MSB(*x, src->data);
289 silc_buffer_pull(src, sizeof(SilcInt64));
292 case SILC_BUFFER_PARAM_UI64_INT:
294 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
295 UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
297 SILC_GET64_MSB(*x, src->data);
298 silc_buffer_pull(src, sizeof(SilcUInt64));
301 case SILC_BUFFER_PARAM_UI8_STRING:
304 unsigned char **x = va_arg(ap, unsigned char **);
305 UNFORMAT_HAS_SPACE(src, 1);
306 len2 = (SilcUInt8)src->data[0];
307 silc_buffer_pull(src, 1);
308 UNFORMAT_HAS_SPACE(src, len2);
311 silc_buffer_pull(src, len2);
314 case SILC_BUFFER_PARAM_UI16_STRING:
317 unsigned char **x = va_arg(ap, unsigned char **);
318 UNFORMAT_HAS_SPACE(src, 2);
319 SILC_GET16_MSB(len2, src->data);
320 silc_buffer_pull(src, 2);
321 UNFORMAT_HAS_SPACE(src, len2);
324 silc_buffer_pull(src, len2);
327 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
330 unsigned char **x = va_arg(ap, unsigned char **);
331 UNFORMAT_HAS_SPACE(src, 1);
332 len2 = (SilcUInt8)src->data[0];
333 silc_buffer_pull(src, 1);
334 UNFORMAT_HAS_SPACE(src, len2);
336 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
337 memcpy(*x, src->data, len2);
339 silc_buffer_pull(src, len2);
342 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
345 unsigned char **x = va_arg(ap, unsigned char **);
346 UNFORMAT_HAS_SPACE(src, 2);
347 SILC_GET16_MSB(len2, src->data);
348 silc_buffer_pull(src, 2);
349 UNFORMAT_HAS_SPACE(src, len2);
351 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
352 memcpy(*x, src->data, len2);
354 silc_buffer_pull(src, len2);
357 case SILC_BUFFER_PARAM_UI32_STRING:
360 unsigned char **x = va_arg(ap, unsigned char **);
361 UNFORMAT_HAS_SPACE(src, 4);
362 SILC_GET32_MSB(len2, src->data);
363 silc_buffer_pull(src, 4);
364 UNFORMAT_HAS_SPACE(src, len2);
367 silc_buffer_pull(src, len2);
370 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
373 unsigned char **x = va_arg(ap, unsigned char **);
374 UNFORMAT_HAS_SPACE(src, 4);
375 SILC_GET32_MSB(len2, src->data);
376 silc_buffer_pull(src, 4);
377 UNFORMAT_HAS_SPACE(src, len2);
379 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
380 memcpy(*x, src->data, len2);
382 silc_buffer_pull(src, len2);
385 case SILC_BUFFER_PARAM_UI8_NSTRING:
388 unsigned char **x = va_arg(ap, unsigned char **);
389 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
390 UNFORMAT_HAS_SPACE(src, 1);
391 len2 = (SilcUInt8)src->data[0];
392 silc_buffer_pull(src, 1);
393 UNFORMAT_HAS_SPACE(src, len2);
398 silc_buffer_pull(src, len2);
401 case SILC_BUFFER_PARAM_UI16_NSTRING:
404 unsigned char **x = va_arg(ap, unsigned char **);
405 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
406 UNFORMAT_HAS_SPACE(src, 2);
407 SILC_GET16_MSB(len2, src->data);
408 silc_buffer_pull(src, 2);
409 UNFORMAT_HAS_SPACE(src, len2);
414 silc_buffer_pull(src, len2);
417 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
420 unsigned char **x = va_arg(ap, unsigned char **);
421 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
422 UNFORMAT_HAS_SPACE(src, 1);
423 len2 = (SilcUInt8)src->data[0];
424 silc_buffer_pull(src, 1);
425 UNFORMAT_HAS_SPACE(src, len2);
429 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
430 memcpy(*x, src->data, len2);
432 silc_buffer_pull(src, len2);
435 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
438 unsigned char **x = va_arg(ap, unsigned char **);
439 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
440 UNFORMAT_HAS_SPACE(src, 2);
441 SILC_GET16_MSB(len2, src->data);
442 silc_buffer_pull(src, 2);
443 UNFORMAT_HAS_SPACE(src, len2);
447 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
448 memcpy(*x, src->data, len2);
450 silc_buffer_pull(src, len2);
453 case SILC_BUFFER_PARAM_UI32_NSTRING:
456 unsigned char **x = va_arg(ap, unsigned char **);
457 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
458 UNFORMAT_HAS_SPACE(src, 4);
459 SILC_GET32_MSB(len2, src->data);
460 silc_buffer_pull(src, 4);
461 UNFORMAT_HAS_SPACE(src, len2);
466 silc_buffer_pull(src, len2);
469 case SILC_BUFFER_PARAM_UI_XNSTRING:
471 unsigned char **x = va_arg(ap, unsigned char **);
472 SilcUInt32 len = va_arg(ap, SilcUInt32);
473 UNFORMAT_HAS_SPACE(src, len);
476 silc_buffer_pull(src, len);
479 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
481 unsigned char **x = va_arg(ap, unsigned char **);
482 SilcUInt32 len = va_arg(ap, SilcUInt32);
483 UNFORMAT_HAS_SPACE(src, len);
485 *x = silc_calloc(len + 1, sizeof(unsigned char));
486 memcpy(*x, src->data, len);
488 silc_buffer_pull(src, len);
491 case SILC_BUFFER_PARAM_END:
495 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
496 "format the data.", fmt));
503 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
504 len = src->data - start_ptr;
505 silc_buffer_push(src, len);
509 /* Push the buffer back to the start. */
510 len = src->data - start_ptr;
511 silc_buffer_push(src, len);
515 /* Formats strings into a buffer */
517 int silc_buffer_strformat(SilcBuffer dst, ...)
519 int len = dst->truelen;
524 /* Parse the arguments by formatting type. */
526 char *string = (char *)va_arg(va, void *);
530 if (string == (char *)SILC_BUFFER_PARAM_END)
533 dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
534 (strlen(string) + len + 1));
537 memcpy(dst->head + len, string, strlen(string));
538 len += strlen(string);
539 dst->head[len] = '\0';
542 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
547 dst->end = dst->head + len;
548 dst->data = dst->head;
549 dst->tail = dst->end;
550 dst->len = dst->truelen = len;