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"));
182 len = dst->data - start_ptr;
183 silc_buffer_push(dst, len);
187 /* Push the buffer back to where it belongs. */
188 len = dst->data - start_ptr;
189 silc_buffer_push(dst, len);
193 /* Unformats the buffer sent as argument. The unformatted data is returned
194 to the variable argument list of pointers. The buffer must point to the
195 start of the data area to be unformatted. Buffer maybe be safely free'd
196 after this returns succesfully. */
198 int silc_buffer_unformat(SilcBuffer src, ...)
204 ret = silc_buffer_unformat_vp(src, ap);
210 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
212 SilcBufferParamType fmt;
213 unsigned char *start_ptr = src->data;
216 /* Parse the arguments by formatting type. */
218 fmt = va_arg(ap, SilcBufferParamType);
221 case SILC_BUFFER_PARAM_SI8_CHAR:
223 char *x = va_arg(ap, char *);
224 MY_HAS_SPACE(src, 1);
227 silc_buffer_pull(src, 1);
230 case SILC_BUFFER_PARAM_UI8_CHAR:
232 unsigned char *x = va_arg(ap, unsigned char *);
233 MY_HAS_SPACE(src, 1);
236 silc_buffer_pull(src, 1);
239 case SILC_BUFFER_PARAM_SI16_SHORT:
241 SilcInt16 *x = va_arg(ap, SilcInt16 *);
242 MY_HAS_SPACE(src, 2);
244 SILC_GET16_MSB(*x, src->data);
245 silc_buffer_pull(src, 2);
248 case SILC_BUFFER_PARAM_UI16_SHORT:
250 SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
251 MY_HAS_SPACE(src, 2);
253 SILC_GET16_MSB(*x, src->data);
254 silc_buffer_pull(src, 2);
257 case SILC_BUFFER_PARAM_SI32_INT:
259 SilcInt32 *x = va_arg(ap, SilcInt32 *);
260 MY_HAS_SPACE(src, 4);
262 SILC_GET32_MSB(*x, src->data);
263 silc_buffer_pull(src, 4);
266 case SILC_BUFFER_PARAM_UI32_INT:
268 SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
269 MY_HAS_SPACE(src, 4);
271 SILC_GET32_MSB(*x, src->data);
272 silc_buffer_pull(src, 4);
275 case SILC_BUFFER_PARAM_SI64_INT:
277 SilcInt64 *x = va_arg(ap, SilcInt64 *);
278 MY_HAS_SPACE(src, sizeof(SilcInt64));
280 SILC_GET64_MSB(*x, src->data);
281 silc_buffer_pull(src, sizeof(SilcInt64));
284 case SILC_BUFFER_PARAM_UI64_INT:
286 SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
287 MY_HAS_SPACE(src, sizeof(SilcUInt64));
289 SILC_GET64_MSB(*x, src->data);
290 silc_buffer_pull(src, sizeof(SilcUInt64));
293 case SILC_BUFFER_PARAM_UI8_STRING:
296 unsigned char **x = va_arg(ap, unsigned char **);
297 MY_HAS_SPACE(src, 1);
298 len2 = (SilcUInt8)src->data[0];
299 silc_buffer_pull(src, 1);
300 MY_HAS_SPACE(src, len2);
303 silc_buffer_pull(src, len2);
306 case SILC_BUFFER_PARAM_UI16_STRING:
309 unsigned char **x = va_arg(ap, unsigned char **);
310 MY_HAS_SPACE(src, 2);
311 SILC_GET16_MSB(len2, src->data);
312 silc_buffer_pull(src, 2);
313 MY_HAS_SPACE(src, len2);
316 silc_buffer_pull(src, len2);
319 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
322 unsigned char **x = va_arg(ap, unsigned char **);
323 MY_HAS_SPACE(src, 1);
324 len2 = (SilcUInt8)src->data[0];
325 silc_buffer_pull(src, 1);
326 MY_HAS_SPACE(src, len2);
328 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
329 memcpy(*x, src->data, len2);
331 silc_buffer_pull(src, len2);
334 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
337 unsigned char **x = va_arg(ap, unsigned char **);
338 MY_HAS_SPACE(src, 2);
339 SILC_GET16_MSB(len2, src->data);
340 silc_buffer_pull(src, 2);
341 MY_HAS_SPACE(src, len2);
343 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
344 memcpy(*x, src->data, len2);
346 silc_buffer_pull(src, len2);
349 case SILC_BUFFER_PARAM_UI32_STRING:
352 unsigned char **x = va_arg(ap, unsigned char **);
353 MY_HAS_SPACE(src, 4);
354 SILC_GET32_MSB(len2, src->data);
355 silc_buffer_pull(src, 4);
356 MY_HAS_SPACE(src, len2);
359 silc_buffer_pull(src, len2);
362 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
365 unsigned char **x = va_arg(ap, unsigned char **);
366 MY_HAS_SPACE(src, 4);
367 SILC_GET32_MSB(len2, src->data);
368 silc_buffer_pull(src, 4);
369 MY_HAS_SPACE(src, len2);
371 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
372 memcpy(*x, src->data, len2);
374 silc_buffer_pull(src, len2);
377 case SILC_BUFFER_PARAM_UI8_NSTRING:
380 unsigned char **x = va_arg(ap, unsigned char **);
381 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
382 MY_HAS_SPACE(src, 1);
383 len2 = (SilcUInt8)src->data[0];
384 silc_buffer_pull(src, 1);
385 MY_HAS_SPACE(src, len2);
390 silc_buffer_pull(src, len2);
393 case SILC_BUFFER_PARAM_UI16_NSTRING:
396 unsigned char **x = va_arg(ap, unsigned char **);
397 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
398 MY_HAS_SPACE(src, 2);
399 SILC_GET16_MSB(len2, src->data);
400 silc_buffer_pull(src, 2);
401 MY_HAS_SPACE(src, len2);
406 silc_buffer_pull(src, len2);
409 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
412 unsigned char **x = va_arg(ap, unsigned char **);
413 SilcUInt8 *len = va_arg(ap, SilcUInt8 *);
414 MY_HAS_SPACE(src, 1);
415 len2 = (SilcUInt8)src->data[0];
416 silc_buffer_pull(src, 1);
417 MY_HAS_SPACE(src, len2);
421 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
422 memcpy(*x, src->data, len2);
424 silc_buffer_pull(src, len2);
427 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
430 unsigned char **x = va_arg(ap, unsigned char **);
431 SilcUInt16 *len = va_arg(ap, SilcUInt16 *);
432 MY_HAS_SPACE(src, 2);
433 SILC_GET16_MSB(len2, src->data);
434 silc_buffer_pull(src, 2);
435 MY_HAS_SPACE(src, len2);
439 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
440 memcpy(*x, src->data, len2);
442 silc_buffer_pull(src, len2);
445 case SILC_BUFFER_PARAM_UI32_NSTRING:
448 unsigned char **x = va_arg(ap, unsigned char **);
449 SilcUInt32 *len = va_arg(ap, SilcUInt32 *);
450 MY_HAS_SPACE(src, 4);
451 SILC_GET32_MSB(len2, src->data);
452 silc_buffer_pull(src, 4);
453 MY_HAS_SPACE(src, len2);
458 silc_buffer_pull(src, len2);
461 case SILC_BUFFER_PARAM_UI_XNSTRING:
463 unsigned char **x = va_arg(ap, unsigned char **);
464 SilcUInt32 len = va_arg(ap, SilcUInt32);
465 MY_HAS_SPACE(src, len);
468 silc_buffer_pull(src, len);
471 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
473 unsigned char **x = va_arg(ap, unsigned char **);
474 SilcUInt32 len = va_arg(ap, SilcUInt32);
475 MY_HAS_SPACE(src, len);
477 *x = silc_calloc(len + 1, sizeof(unsigned char));
478 memcpy(*x, src->data, len);
480 silc_buffer_pull(src, len);
483 case SILC_BUFFER_PARAM_END:
487 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
488 "format the data.", fmt));
495 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
496 len = src->data - start_ptr;
497 silc_buffer_push(src, len);
501 /* Push the buffer back to the start. */
502 len = src->data - start_ptr;
503 silc_buffer_push(src, len);
507 /* Formats strings into a buffer */
509 int silc_buffer_strformat(SilcBuffer dst, ...)
511 int len = dst->truelen;
516 /* Parse the arguments by formatting type. */
518 char *string = va_arg(va, char *);
522 if (string == (char *)SILC_BUFFER_PARAM_END)
525 dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
526 (strlen(string) + len));
527 memcpy(dst->head + len, string, strlen(string));
528 len += strlen(string);
531 SILC_LOG_DEBUG(("Error occured while formatting buffer"));
536 dst->end = dst->head + len;
537 dst->tail = dst->data = dst->end;