5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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 HAS_SPACE(x, req) \
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, ...)
43 SilcBufferParamType fmt;
44 unsigned char *start_ptr = dst->data;
48 /* Parse the arguments by formatting type. */
50 fmt = va_arg(ap, SilcBufferParamType);
53 case SILC_BUFFER_PARAM_SI8_CHAR:
55 char x = (char)va_arg(ap, int);
57 silc_buffer_put(dst, &x, 1);
58 silc_buffer_pull(dst, 1);
61 case SILC_BUFFER_PARAM_UI8_CHAR:
63 unsigned char x = (unsigned char)va_arg(ap, int);
65 silc_buffer_put(dst, &x, 1);
66 silc_buffer_pull(dst, 1);
69 case SILC_BUFFER_PARAM_SI16_SHORT:
72 int16 x = (int16)va_arg(ap, int);
74 SILC_PUT16_MSB(x, xf);
75 silc_buffer_put(dst, xf, 2);
76 silc_buffer_pull(dst, 2);
79 case SILC_BUFFER_PARAM_UI16_SHORT:
82 uint16 x = (uint16)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_SI32_INT:
92 int32 x = va_arg(ap, int32);
94 SILC_PUT32_MSB(x, xf);
95 silc_buffer_put(dst, xf, 4);
96 silc_buffer_pull(dst, 4);
99 case SILC_BUFFER_PARAM_UI32_INT:
102 uint32 x = va_arg(ap, uint32);
104 SILC_PUT32_MSB(x, xf);
105 silc_buffer_put(dst, xf, 4);
106 silc_buffer_pull(dst, 4);
109 case SILC_BUFFER_PARAM_UI16_STRING:
110 case SILC_BUFFER_PARAM_UI32_STRING:
111 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
112 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
114 unsigned char *x = va_arg(ap, unsigned char *);
115 uint32 tmp_len = strlen(x);
116 HAS_SPACE(dst, tmp_len);
117 silc_buffer_put(dst, x, tmp_len);
118 silc_buffer_pull(dst, tmp_len);
121 case SILC_BUFFER_PARAM_UI16_NSTRING:
122 case SILC_BUFFER_PARAM_UI32_NSTRING:
123 case SILC_BUFFER_PARAM_UI_XNSTRING:
124 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
125 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
126 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
128 unsigned char *x = va_arg(ap, unsigned char *);
129 uint32 len = va_arg(ap, uint32);
131 silc_buffer_put(dst, x, len);
132 silc_buffer_pull(dst, len);
135 case SILC_BUFFER_PARAM_END:
139 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
140 "format the data.", fmt));
147 SILC_LOG_DEBUG(("Error occured while formatting data"));
151 /* Push the buffer back to where it belongs. */
152 silc_buffer_push(dst, dst->data - start_ptr);
156 /* Unformats the buffer sent as argument. The unformatted data is returned
157 to the variable argument list of pointers. The buffer must point to the
158 start of the data area to be unformatted. Buffer maybe be safely free'd
159 after this returns succesfully. */
161 int silc_buffer_unformat(SilcBuffer src, ...)
164 SilcBufferParamType fmt;
165 unsigned char *start_ptr = src->data;
170 /* Parse the arguments by formatting type. */
172 fmt = va_arg(ap, SilcBufferParamType);
175 case SILC_BUFFER_PARAM_SI8_CHAR:
177 char *x = va_arg(ap, char *);
181 silc_buffer_pull(src, 1);
184 case SILC_BUFFER_PARAM_UI8_CHAR:
186 unsigned char *x = va_arg(ap, unsigned char *);
190 silc_buffer_pull(src, 1);
193 case SILC_BUFFER_PARAM_SI16_SHORT:
195 int16 *x = va_arg(ap, int16 *);
198 SILC_GET16_MSB(*x, src->data);
199 silc_buffer_pull(src, 2);
202 case SILC_BUFFER_PARAM_UI16_SHORT:
204 uint16 *x = va_arg(ap, uint16 *);
207 SILC_GET16_MSB(*x, src->data);
208 silc_buffer_pull(src, 2);
211 case SILC_BUFFER_PARAM_SI32_INT:
213 int32 *x = va_arg(ap, int32 *);
216 SILC_GET32_MSB(*x, src->data);
217 silc_buffer_pull(src, 4);
220 case SILC_BUFFER_PARAM_UI32_INT:
222 uint32 *x = va_arg(ap, uint32 *);
225 SILC_GET32_MSB(*x, src->data);
226 silc_buffer_pull(src, 4);
229 case SILC_BUFFER_PARAM_UI16_STRING:
232 unsigned char **x = va_arg(ap, unsigned char **);
234 SILC_GET16_MSB(len2, src->data);
235 silc_buffer_pull(src, 2);
236 HAS_SPACE(src, len2);
239 silc_buffer_pull(src, len2);
242 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
245 unsigned char **x = va_arg(ap, unsigned char **);
247 SILC_GET16_MSB(len2, src->data);
248 silc_buffer_pull(src, 2);
249 HAS_SPACE(src, len2);
251 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
252 memcpy(*x, src->data, len2);
254 silc_buffer_pull(src, len2);
257 case SILC_BUFFER_PARAM_UI32_STRING:
260 unsigned char **x = va_arg(ap, unsigned char **);
262 SILC_GET32_MSB(len2, src->data);
263 silc_buffer_pull(src, 4);
264 HAS_SPACE(src, len2);
267 silc_buffer_pull(src, len2);
270 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
273 unsigned char **x = va_arg(ap, unsigned char **);
275 SILC_GET32_MSB(len2, src->data);
276 silc_buffer_pull(src, 4);
277 HAS_SPACE(src, len2);
279 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
280 memcpy(*x, src->data, len2);
282 silc_buffer_pull(src, len2);
285 case SILC_BUFFER_PARAM_UI16_NSTRING:
288 unsigned char **x = va_arg(ap, unsigned char **);
289 uint16 *len = va_arg(ap, unsigned short *);
291 SILC_GET16_MSB(len2, src->data);
292 silc_buffer_pull(src, 2);
293 HAS_SPACE(src, len2);
298 silc_buffer_pull(src, len2);
301 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
304 unsigned char **x = va_arg(ap, unsigned char **);
305 uint16 *len = va_arg(ap, uint16 *);
307 SILC_GET16_MSB(len2, src->data);
308 silc_buffer_pull(src, 2);
309 HAS_SPACE(src, len2);
313 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
314 memcpy(*x, src->data, len2);
316 silc_buffer_pull(src, len2);
319 case SILC_BUFFER_PARAM_UI32_NSTRING:
322 unsigned char **x = va_arg(ap, unsigned char **);
323 uint32 *len = va_arg(ap, uint32 *);
325 SILC_GET32_MSB(len2, src->data);
326 silc_buffer_pull(src, 4);
327 HAS_SPACE(src, len2);
332 silc_buffer_pull(src, len2);
335 case SILC_BUFFER_PARAM_UI_XNSTRING:
337 unsigned char **x = va_arg(ap, unsigned char **);
338 uint32 len = va_arg(ap, uint32);
342 silc_buffer_pull(src, len);
345 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
347 unsigned char **x = va_arg(ap, unsigned char **);
348 uint32 len = va_arg(ap, uint32);
351 *x = silc_calloc(len + 1, sizeof(unsigned char));
352 memcpy(*x, src->data, len);
354 silc_buffer_pull(src, len);
357 case SILC_BUFFER_PARAM_END:
361 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
362 "format the data.", fmt));
369 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
373 /* Push the buffer back to the start. */
374 len = src->data - start_ptr;
375 silc_buffer_push(src, len);