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);
165 MY_HAS_SPACE(dst, len);
166 silc_buffer_put(dst, x, len);
167 silc_buffer_pull(dst, len);
171 case SILC_BUFFER_PARAM_END:
175 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
176 "format the data.", fmt));
183 SILC_LOG_DEBUG(("Error occured while formatting data"));
184 len = dst->data - start_ptr;
185 silc_buffer_push(dst, len);
189 /* Push the buffer back to where it belongs. */
190 len = dst->data - start_ptr;
191 silc_buffer_push(dst, len);
195 /* Unformats the buffer sent as argument. The unformatted data is returned
196 to the variable argument list of pointers. The buffer must point to the
197 start of the data area to be unformatted. Buffer maybe be safely free'd
198 after this returns succesfully. */
200 int silc_buffer_unformat(SilcBuffer src, ...)
206 ret = silc_buffer_unformat_vp(src, ap);
212 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
214 SilcBufferParamType fmt;
215 unsigned char *start_ptr = src->data;
218 /* Parse the arguments by formatting type. */
220 fmt = va_arg(ap, SilcBufferParamType);
223 case SILC_BUFFER_PARAM_SI8_CHAR:
225 char *x = va_arg(ap, char *);
226 MY_HAS_SPACE(src, 1);
229 silc_buffer_pull(src, 1);
232 case SILC_BUFFER_PARAM_UI8_CHAR:
234 unsigned char *x = va_arg(ap, unsigned char *);
235 MY_HAS_SPACE(src, 1);
238 silc_buffer_pull(src, 1);
241 case SILC_BUFFER_PARAM_SI16_SHORT:
243 SilcInt16 *x = va_arg(ap, SilcInt16 *);
244 MY_HAS_SPACE(src, 2);
246 SILC_GET16_MSB(*x, src->data);
247 silc_buffer_pull(src, 2);
250 case SILC_BUFFER_PARAM_UI16_SHORT:
252 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
253 MY_HAS_SPACE(src, 2);
255 SILC_GET16_MSB(*x, src->data);
256 silc_buffer_pull(src, 2);
259 case SILC_BUFFER_PARAM_SI32_INT:
261 SilcInt32 *x = va_arg(ap, SilcInt32 *);
262 MY_HAS_SPACE(src, 4);
264 SILC_GET32_MSB(*x, src->data);
265 silc_buffer_pull(src, 4);
268 case SILC_BUFFER_PARAM_UI32_INT:
270 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
271 MY_HAS_SPACE(src, 4);
273 SILC_GET32_MSB(*x, src->data);
274 silc_buffer_pull(src, 4);
277 case SILC_BUFFER_PARAM_SI64_INT:
279 SilcInt64 *x = va_arg(ap, SilcInt64 *);
280 MY_HAS_SPACE(src, sizeof(SilcInt64));
282 SILC_GET64_MSB(*x, src->data);
283 silc_buffer_pull(src, sizeof(SilcInt64));
286 case SILC_BUFFER_PARAM_UI64_INT:
288 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
289 MY_HAS_SPACE(src, sizeof(SilcUInt64));
291 SILC_GET64_MSB(*x, src->data);
292 silc_buffer_pull(src, sizeof(SilcUInt64));
295 case SILC_BUFFER_PARAM_UI8_STRING:
298 unsigned char **x = va_arg(ap, unsigned char **);
299 MY_HAS_SPACE(src, 1);
300 len2 = (SilcUInt8)src->data[0];
301 silc_buffer_pull(src, 1);
302 MY_HAS_SPACE(src, len2);
305 silc_buffer_pull(src, len2);
308 case SILC_BUFFER_PARAM_UI16_STRING:
311 unsigned char **x = va_arg(ap, unsigned char **);
312 MY_HAS_SPACE(src, 2);
313 SILC_GET16_MSB(len2, src->data);
314 silc_buffer_pull(src, 2);
315 MY_HAS_SPACE(src, len2);
318 silc_buffer_pull(src, len2);
321 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
324 unsigned char **x = va_arg(ap, unsigned char **);
325 MY_HAS_SPACE(src, 1);
326 len2 = (SilcUInt8)src->data[0];
327 silc_buffer_pull(src, 1);
328 MY_HAS_SPACE(src, len2);
330 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
331 memcpy(*x, src->data, len2);
333 silc_buffer_pull(src, len2);
336 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
339 unsigned char **x = va_arg(ap, unsigned char **);
340 MY_HAS_SPACE(src, 2);
341 SILC_GET16_MSB(len2, src->data);
342 silc_buffer_pull(src, 2);
343 MY_HAS_SPACE(src, len2);
345 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
346 memcpy(*x, src->data, len2);
348 silc_buffer_pull(src, len2);
351 case SILC_BUFFER_PARAM_UI32_STRING:
354 unsigned char **x = va_arg(ap, unsigned char **);
355 MY_HAS_SPACE(src, 4);
356 SILC_GET32_MSB(len2, src->data);
357 silc_buffer_pull(src, 4);
358 MY_HAS_SPACE(src, len2);
361 silc_buffer_pull(src, len2);
364 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
367 unsigned char **x = va_arg(ap, unsigned char **);
368 MY_HAS_SPACE(src, 4);
369 SILC_GET32_MSB(len2, src->data);
370 silc_buffer_pull(src, 4);
371 MY_HAS_SPACE(src, len2);
373 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
374 memcpy(*x, src->data, len2);
376 silc_buffer_pull(src, len2);
379 case SILC_BUFFER_PARAM_UI8_NSTRING:
382 unsigned char **x = va_arg(ap, unsigned char **);
383 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
384 MY_HAS_SPACE(src, 1);
385 len2 = (SilcUInt8)src->data[0];
386 silc_buffer_pull(src, 1);
387 MY_HAS_SPACE(src, len2);
392 silc_buffer_pull(src, len2);
395 case SILC_BUFFER_PARAM_UI16_NSTRING:
398 unsigned char **x = va_arg(ap, unsigned char **);
399 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
400 MY_HAS_SPACE(src, 2);
401 SILC_GET16_MSB(len2, src->data);
402 silc_buffer_pull(src, 2);
403 MY_HAS_SPACE(src, len2);
408 silc_buffer_pull(src, len2);
411 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
414 unsigned char **x = va_arg(ap, unsigned char **);
415 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
416 MY_HAS_SPACE(src, 1);
417 len2 = (SilcUInt8)src->data[0];
418 silc_buffer_pull(src, 1);
419 MY_HAS_SPACE(src, len2);
423 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
424 memcpy(*x, src->data, len2);
426 silc_buffer_pull(src, len2);
429 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
432 unsigned char **x = va_arg(ap, unsigned char **);
433 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
434 MY_HAS_SPACE(src, 2);
435 SILC_GET16_MSB(len2, src->data);
436 silc_buffer_pull(src, 2);
437 MY_HAS_SPACE(src, len2);
441 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
442 memcpy(*x, src->data, len2);
444 silc_buffer_pull(src, len2);
447 case SILC_BUFFER_PARAM_UI32_NSTRING:
450 unsigned char **x = va_arg(ap, unsigned char **);
451 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
452 MY_HAS_SPACE(src, 4);
453 SILC_GET32_MSB(len2, src->data);
454 silc_buffer_pull(src, 4);
455 MY_HAS_SPACE(src, len2);
460 silc_buffer_pull(src, len2);
463 case SILC_BUFFER_PARAM_UI_XNSTRING:
465 unsigned char **x = va_arg(ap, unsigned char **);
466 SilcUInt32 len = va_arg(ap, SilcUInt32);
467 MY_HAS_SPACE(src, len);
470 silc_buffer_pull(src, len);
473 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
475 unsigned char **x = va_arg(ap, unsigned char **);
476 SilcUInt32 len = va_arg(ap, SilcUInt32);
477 MY_HAS_SPACE(src, len);
479 *x = silc_calloc(len + 1, sizeof(unsigned char));
480 memcpy(*x, src->data, len);
482 silc_buffer_pull(src, len);
485 case SILC_BUFFER_PARAM_END:
489 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
490 "format the data.", fmt));
497 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
498 len = src->data - start_ptr;
499 silc_buffer_push(src, len);
503 /* Push the buffer back to the start. */
504 len = src->data - start_ptr;
505 silc_buffer_push(src, len);
509 /* Formats strings into a buffer */
511 int silc_buffer_strformat(SilcBuffer dst, ...)
513 int len = dst->truelen;
518 /* Parse the arguments by formatting type. */
520 char *string = va_arg(va, char *);
524 if (string == (char *)SILC_BUFFER_PARAM_END)
527 dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
528 (strlen(string) + len));
529 memcpy(dst->head + len, string, strlen(string));
530 len += strlen(string);
533 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
538 dst->end = dst->head + len;
539 dst->tail = dst->data = dst->end;