Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015, Vsevolod Stakhov
3 : : * All rights reserved.
4 : : *
5 : : * Redistribution and use in source and binary forms, with or without
6 : : * modification, are permitted provided that the following conditions are met:
7 : : * * Redistributions of source code must retain the above copyright
8 : : * notice, this list of conditions and the following disclaimer.
9 : : * * Redistributions in binary form must reproduce the above copyright
10 : : * notice, this list of conditions and the following disclaimer in the
11 : : * documentation and/or other materials provided with the distribution.
12 : : *
13 : : * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
14 : : * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 : : * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 : : * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
17 : : * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 : : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 : : * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 : : */
24 : :
25 : :
26 : : #ifdef HAVE_CONFIG_H
27 : : #include "config.h"
28 : : #endif
29 : :
30 : : #include "ucl.h"
31 : : #include "ucl_internal.h"
32 : :
33 : : #ifdef HAVE_ENDIAN_H
34 : : #include <endian.h>
35 : : #elif defined(HAVE_SYS_ENDIAN_H)
36 : : #include <sys/endian.h>
37 : : #elif defined(HAVE_MACHINE_ENDIAN_H)
38 : : #include <machine/endian.h>
39 : : #endif
40 : :
41 : : #if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
42 : : #if __BYTE_ORDER == __LITTLE_ENDIAN
43 : : #define __LITTLE_ENDIAN__
44 : : #elif __BYTE_ORDER == __BIG_ENDIAN
45 : : #define __BIG_ENDIAN__
46 : : #elif _WIN32
47 : : #define __LITTLE_ENDIAN__
48 : : #endif
49 : : #endif
50 : :
51 : : #define SWAP_LE_BE16(val) ((uint16_t) ( \
52 : : (uint16_t) ((uint16_t) (val) >> 8) | \
53 : : (uint16_t) ((uint16_t) (val) << 8)))
54 : :
55 : : #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 4 && defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 3)
56 : : # define SWAP_LE_BE32(val) ((uint32_t)__builtin_bswap32 ((uint32_t)(val)))
57 : : # define SWAP_LE_BE64(val) ((uint64_t)__builtin_bswap64 ((uint64_t)(val)))
58 : : #else
59 : : #define SWAP_LE_BE32(val) ((uint32_t)( \
60 : : (((uint32_t)(val) & (uint32_t)0x000000ffU) << 24) | \
61 : : (((uint32_t)(val) & (uint32_t)0x0000ff00U) << 8) | \
62 : : (((uint32_t)(val) & (uint32_t)0x00ff0000U) >> 8) | \
63 : : (((uint32_t)(val) & (uint32_t)0xff000000U) >> 24)))
64 : :
65 : : #define SWAP_LE_BE64(val) ((uint64_t)( \
66 : : (((uint64_t)(val) & \
67 : : (uint64_t)(0x00000000000000ffULL)) << 56) | \
68 : : (((uint64_t)(val) & \
69 : : (uint64_t)(0x000000000000ff00ULL)) << 40) | \
70 : : (((uint64_t)(val) & \
71 : : (uint64_t)(0x0000000000ff0000ULL)) << 24) | \
72 : : (((uint64_t)(val) & \
73 : : (uint64_t) (0x00000000ff000000ULL)) << 8) | \
74 : : (((uint64_t)(val) & \
75 : : (uint64_t)(0x000000ff00000000ULL)) >> 8) | \
76 : : (((uint64_t)(val) & \
77 : : (uint64_t)(0x0000ff0000000000ULL)) >> 24) | \
78 : : (((uint64_t)(val) & \
79 : : (uint64_t)(0x00ff000000000000ULL)) >> 40) | \
80 : : (((uint64_t)(val) & \
81 : : (uint64_t)(0xff00000000000000ULL)) >> 56)))
82 : : #endif
83 : :
84 : : #ifdef __LITTLE_ENDIAN__
85 : : #define TO_BE16 SWAP_LE_BE16
86 : : #define TO_BE32 SWAP_LE_BE32
87 : : #define TO_BE64 SWAP_LE_BE64
88 : : #define FROM_BE16 SWAP_LE_BE16
89 : : #define FROM_BE32 SWAP_LE_BE32
90 : : #define FROM_BE64 SWAP_LE_BE64
91 : : #else
92 : : #define TO_BE16(val) (uint16_t)(val)
93 : : #define TO_BE32(val) (uint32_t)(val)
94 : : #define TO_BE64(val) (uint64_t)(val)
95 : : #define FROM_BE16(val) (uint16_t)(val)
96 : : #define FROM_BE32(val) (uint32_t)(val)
97 : : #define FROM_BE64(val) (uint64_t)(val)
98 : : #endif
99 : :
100 : : void
101 : 0 : ucl_emitter_print_int_msgpack (struct ucl_emitter_context *ctx, int64_t val)
102 : : {
103 : 0 : const struct ucl_emitter_functions *func = ctx->func;
104 : : unsigned char buf[sizeof(uint64_t) + 1];
105 : 0 : const unsigned char mask_positive = 0x7f, mask_negative = 0xe0,
106 : 0 : uint8_ch = 0xcc, uint16_ch = 0xcd, uint32_ch = 0xce, uint64_ch = 0xcf,
107 : 0 : int8_ch = 0xd0, int16_ch = 0xd1, int32_ch = 0xd2, int64_ch = 0xd3;
108 : : unsigned len;
109 : :
110 [ # # ]: 0 : if (val >= 0) {
111 [ # # ]: 0 : if (val <= 0x7f) {
112 : : /* Fixed num 7 bits */
113 : 0 : len = 1;
114 : 0 : buf[0] = mask_positive & val;
115 : 0 : }
116 [ # # ]: 0 : else if (val <= UINT8_MAX) {
117 : 0 : len = 2;
118 : 0 : buf[0] = uint8_ch;
119 : 0 : buf[1] = val & 0xff;
120 : 0 : }
121 [ # # ]: 0 : else if (val <= UINT16_MAX) {
122 : 0 : uint16_t v = TO_BE16 (val);
123 : :
124 : 0 : len = 3;
125 : 0 : buf[0] = uint16_ch;
126 : 0 : memcpy (&buf[1], &v, sizeof (v));
127 : 0 : }
128 [ # # ]: 0 : else if (val <= UINT32_MAX) {
129 : 0 : uint32_t v = TO_BE32 (val);
130 : :
131 : 0 : len = 5;
132 : 0 : buf[0] = uint32_ch;
133 : 0 : memcpy (&buf[1], &v, sizeof (v));
134 : 0 : }
135 : : else {
136 : 0 : uint64_t v = TO_BE64 (val);
137 : :
138 : 0 : len = 9;
139 : 0 : buf[0] = uint64_ch;
140 : 0 : memcpy (&buf[1], &v, sizeof (v));
141 : : }
142 : 0 : }
143 : : else {
144 : : uint64_t uval;
145 : : /* Bithack abs */
146 : 0 : uval = ((val ^ (val >> 63)) - (val >> 63));
147 : :
148 [ # # ]: 0 : if (val > -(1 << 5)) {
149 : 0 : len = 1;
150 : 0 : buf[0] = (mask_negative | uval) & 0xff;
151 : 0 : }
152 [ # # ]: 0 : else if (uval <= INT8_MAX) {
153 : 0 : uint8_t v = (uint8_t)val;
154 : 0 : len = 2;
155 : 0 : buf[0] = int8_ch;
156 : 0 : buf[1] = v;
157 : 0 : }
158 [ # # ]: 0 : else if (uval <= INT16_MAX) {
159 : 0 : uint16_t v = TO_BE16 (val);
160 : :
161 : 0 : len = 3;
162 : 0 : buf[0] = int16_ch;
163 : 0 : memcpy (&buf[1], &v, sizeof (v));
164 : 0 : }
165 [ # # ]: 0 : else if (uval <= INT32_MAX) {
166 : 0 : uint32_t v = TO_BE32 (val);
167 : :
168 : 0 : len = 5;
169 : 0 : buf[0] = int32_ch;
170 : 0 : memcpy (&buf[1], &v, sizeof (v));
171 : 0 : }
172 : : else {
173 : 0 : uint64_t v = TO_BE64 (val);
174 : :
175 : 0 : len = 9;
176 : 0 : buf[0] = int64_ch;
177 : 0 : memcpy (&buf[1], &v, sizeof (v));
178 : : }
179 : : }
180 : :
181 : 0 : func->ucl_emitter_append_len (buf, len, func->ud);
182 : 0 : }
183 : :
184 : : void
185 : 0 : ucl_emitter_print_double_msgpack (struct ucl_emitter_context *ctx, double val)
186 : : {
187 : 0 : const struct ucl_emitter_functions *func = ctx->func;
188 : : union {
189 : : double d;
190 : : uint64_t i;
191 : : } u;
192 : 0 : const unsigned char dbl_ch = 0xcb;
193 : : unsigned char buf[sizeof(double) + 1];
194 : :
195 : : /* Convert to big endian */
196 : 0 : u.d = val;
197 : 0 : u.i = TO_BE64 (u.i);
198 : :
199 : 0 : buf[0] = dbl_ch;
200 : 0 : memcpy (&buf[1], &u.d, sizeof (double));
201 : 0 : func->ucl_emitter_append_len (buf, sizeof (buf), func->ud);
202 : 0 : }
203 : :
204 : : void
205 : 0 : ucl_emitter_print_bool_msgpack (struct ucl_emitter_context *ctx, bool val)
206 : : {
207 : 0 : const struct ucl_emitter_functions *func = ctx->func;
208 : 0 : const unsigned char true_ch = 0xc3, false_ch = 0xc2;
209 : :
210 : 0 : func->ucl_emitter_append_character (val ? true_ch : false_ch, 1, func->ud);
211 : 0 : }
212 : :
213 : : void
214 : 0 : ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
215 : : const char *s, size_t len)
216 : : {
217 : 0 : const struct ucl_emitter_functions *func = ctx->func;
218 : 0 : const unsigned char fix_mask = 0xA0, l8_ch = 0xd9, l16_ch = 0xda, l32_ch = 0xdb;
219 : : unsigned char buf[5];
220 : : unsigned blen;
221 : :
222 [ # # ]: 0 : if (len <= 0x1F) {
223 : 0 : blen = 1;
224 : 0 : buf[0] = (len | fix_mask) & 0xff;
225 : 0 : }
226 [ # # ]: 0 : else if (len <= 0xff) {
227 : 0 : blen = 2;
228 : 0 : buf[0] = l8_ch;
229 : 0 : buf[1] = len & 0xff;
230 : 0 : }
231 [ # # ]: 0 : else if (len <= 0xffff) {
232 : 0 : uint16_t bl = TO_BE16 (len);
233 : :
234 : 0 : blen = 3;
235 : 0 : buf[0] = l16_ch;
236 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
237 : 0 : }
238 : : else {
239 : 0 : uint32_t bl = TO_BE32 (len);
240 : :
241 : 0 : blen = 5;
242 : 0 : buf[0] = l32_ch;
243 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
244 : : }
245 : :
246 : 0 : func->ucl_emitter_append_len (buf, blen, func->ud);
247 : 0 : func->ucl_emitter_append_len (s, len, func->ud);
248 : 0 : }
249 : :
250 : : void
251 : 0 : ucl_emitter_print_binary_string_msgpack (struct ucl_emitter_context *ctx,
252 : : const char *s, size_t len)
253 : : {
254 : 0 : const struct ucl_emitter_functions *func = ctx->func;
255 : 0 : const unsigned char l8_ch = 0xc4, l16_ch = 0xc5, l32_ch = 0xc6;
256 : : unsigned char buf[5];
257 : : unsigned blen;
258 : :
259 [ # # ]: 0 : if (len <= 0xff) {
260 : 0 : blen = 2;
261 : 0 : buf[0] = l8_ch;
262 : 0 : buf[1] = len & 0xff;
263 : 0 : }
264 [ # # ]: 0 : else if (len <= 0xffff) {
265 : 0 : uint16_t bl = TO_BE16 (len);
266 : :
267 : 0 : blen = 3;
268 : 0 : buf[0] = l16_ch;
269 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
270 : 0 : }
271 : : else {
272 : 0 : uint32_t bl = TO_BE32 (len);
273 : :
274 : 0 : blen = 5;
275 : 0 : buf[0] = l32_ch;
276 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
277 : : }
278 : :
279 : 0 : func->ucl_emitter_append_len (buf, blen, func->ud);
280 : 0 : func->ucl_emitter_append_len (s, len, func->ud);
281 : 0 : }
282 : :
283 : : void
284 : 0 : ucl_emitter_print_null_msgpack (struct ucl_emitter_context *ctx)
285 : : {
286 : 0 : const struct ucl_emitter_functions *func = ctx->func;
287 : 0 : const unsigned char nil = 0xc0;
288 : :
289 : 0 : func->ucl_emitter_append_character (nil, 1, func->ud);
290 : 0 : }
291 : :
292 : : void
293 : 0 : ucl_emitter_print_key_msgpack (bool print_key, struct ucl_emitter_context *ctx,
294 : : const ucl_object_t *obj)
295 : : {
296 [ # # ]: 0 : if (print_key) {
297 : 0 : ucl_emitter_print_string_msgpack (ctx, obj->key, obj->keylen);
298 : 0 : }
299 : 0 : }
300 : :
301 : : void
302 : 0 : ucl_emitter_print_array_msgpack (struct ucl_emitter_context *ctx, size_t len)
303 : : {
304 : 0 : const struct ucl_emitter_functions *func = ctx->func;
305 : 0 : const unsigned char fix_mask = 0x90, l16_ch = 0xdc, l32_ch = 0xdd;
306 : : unsigned char buf[5];
307 : : unsigned blen;
308 : :
309 [ # # ]: 0 : if (len <= 0xF) {
310 : 0 : blen = 1;
311 : 0 : buf[0] = (len | fix_mask) & 0xff;
312 : 0 : }
313 [ # # ]: 0 : else if (len <= 0xffff) {
314 : 0 : uint16_t bl = TO_BE16 (len);
315 : :
316 : 0 : blen = 3;
317 : 0 : buf[0] = l16_ch;
318 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
319 : 0 : }
320 : : else {
321 : 0 : uint32_t bl = TO_BE32 (len);
322 : :
323 : 0 : blen = 5;
324 : 0 : buf[0] = l32_ch;
325 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
326 : : }
327 : :
328 : 0 : func->ucl_emitter_append_len (buf, blen, func->ud);
329 : 0 : }
330 : :
331 : : void
332 : 0 : ucl_emitter_print_object_msgpack (struct ucl_emitter_context *ctx, size_t len)
333 : : {
334 : 0 : const struct ucl_emitter_functions *func = ctx->func;
335 : 0 : const unsigned char fix_mask = 0x80, l16_ch = 0xde, l32_ch = 0xdf;
336 : : unsigned char buf[5];
337 : : unsigned blen;
338 : :
339 [ # # ]: 0 : if (len <= 0xF) {
340 : 0 : blen = 1;
341 : 0 : buf[0] = (len | fix_mask) & 0xff;
342 : 0 : }
343 [ # # ]: 0 : else if (len <= 0xffff) {
344 : 0 : uint16_t bl = TO_BE16 (len);
345 : :
346 : 0 : blen = 3;
347 : 0 : buf[0] = l16_ch;
348 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
349 : 0 : }
350 : : else {
351 : 0 : uint32_t bl = TO_BE32 (len);
352 : :
353 : 0 : blen = 5;
354 : 0 : buf[0] = l32_ch;
355 : 0 : memcpy (&buf[1], &bl, sizeof (bl));
356 : : }
357 : :
358 : 0 : func->ucl_emitter_append_len (buf, blen, func->ud);
359 : 0 : }
360 : :
361 : :
362 : : enum ucl_msgpack_format {
363 : : msgpack_positive_fixint = 0,
364 : : msgpack_fixmap,
365 : : msgpack_fixarray,
366 : : msgpack_fixstr,
367 : : msgpack_nil,
368 : : msgpack_false,
369 : : msgpack_true,
370 : : msgpack_bin8,
371 : : msgpack_bin16,
372 : : msgpack_bin32,
373 : : msgpack_ext8,
374 : : msgpack_ext16,
375 : : msgpack_ext32,
376 : : msgpack_float32,
377 : : msgpack_float64,
378 : : msgpack_uint8,
379 : : msgpack_uint16,
380 : : msgpack_uint32,
381 : : msgpack_uint64,
382 : : msgpack_int8,
383 : : msgpack_int16,
384 : : msgpack_int32,
385 : : msgpack_int64,
386 : : msgpack_fixext1,
387 : : msgpack_fixext2,
388 : : msgpack_fixext4,
389 : : msgpack_fixext8,
390 : : msgpack_fixext16,
391 : : msgpack_str8,
392 : : msgpack_str16,
393 : : msgpack_str32,
394 : : msgpack_array16,
395 : : msgpack_array32,
396 : : msgpack_map16,
397 : : msgpack_map32,
398 : : msgpack_negative_fixint,
399 : : msgpack_invalid
400 : : };
401 : :
402 : : typedef ssize_t (*ucl_msgpack_parse_function)(struct ucl_parser *parser,
403 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
404 : : const unsigned char *pos, size_t remain);
405 : :
406 : : static ssize_t ucl_msgpack_parse_map (struct ucl_parser *parser,
407 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
408 : : const unsigned char *pos, size_t remain);
409 : : static ssize_t ucl_msgpack_parse_array (struct ucl_parser *parser,
410 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
411 : : const unsigned char *pos, size_t remain);
412 : : static ssize_t ucl_msgpack_parse_string (struct ucl_parser *parser,
413 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
414 : : const unsigned char *pos, size_t remain);
415 : : static ssize_t ucl_msgpack_parse_int (struct ucl_parser *parser,
416 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
417 : : const unsigned char *pos, size_t remain);
418 : : static ssize_t ucl_msgpack_parse_float (struct ucl_parser *parser,
419 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
420 : : const unsigned char *pos, size_t remain);
421 : : static ssize_t ucl_msgpack_parse_bool (struct ucl_parser *parser,
422 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
423 : : const unsigned char *pos, size_t remain);
424 : : static ssize_t ucl_msgpack_parse_null (struct ucl_parser *parser,
425 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
426 : : const unsigned char *pos, size_t remain);
427 : : static ssize_t ucl_msgpack_parse_ignore (struct ucl_parser *parser,
428 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
429 : : const unsigned char *pos, size_t remain);
430 : :
431 : : #define MSGPACK_FLAG_FIXED (1 << 0)
432 : : #define MSGPACK_FLAG_CONTAINER (1 << 1)
433 : : #define MSGPACK_FLAG_TYPEVALUE (1 << 2)
434 : : #define MSGPACK_FLAG_EXT (1 << 3)
435 : : #define MSGPACK_FLAG_ASSOC (1 << 4)
436 : : #define MSGPACK_FLAG_KEY (1 << 5)
437 : :
438 : : /*
439 : : * Search tree packed in array
440 : : */
441 : : struct ucl_msgpack_parser {
442 : : uint8_t prefix; /* Prefix byte */
443 : : uint8_t prefixlen; /* Length of prefix in bits */
444 : : uint8_t fmt; /* The desired format */
445 : : uint8_t len; /* Length of the object
446 : : (either length bytes
447 : : or length of value in case
448 : : of fixed objects */
449 : : uint8_t flags; /* Flags of the specified type */
450 : : ucl_msgpack_parse_function func; /* Parser function */
451 : : } parsers[] = {
452 : : {
453 : : 0xa0,
454 : : 3,
455 : : msgpack_fixstr,
456 : : 0,
457 : : MSGPACK_FLAG_FIXED|MSGPACK_FLAG_KEY,
458 : : ucl_msgpack_parse_string
459 : : },
460 : : {
461 : : 0x0,
462 : : 1,
463 : : msgpack_positive_fixint,
464 : : 0,
465 : : MSGPACK_FLAG_FIXED|MSGPACK_FLAG_TYPEVALUE,
466 : : ucl_msgpack_parse_int
467 : : },
468 : : {
469 : : 0xe0,
470 : : 3,
471 : : msgpack_negative_fixint,
472 : : 0,
473 : : MSGPACK_FLAG_FIXED|MSGPACK_FLAG_TYPEVALUE,
474 : : ucl_msgpack_parse_int
475 : : },
476 : : {
477 : : 0x80,
478 : : 4,
479 : : msgpack_fixmap,
480 : : 0,
481 : : MSGPACK_FLAG_FIXED|MSGPACK_FLAG_CONTAINER|MSGPACK_FLAG_ASSOC,
482 : : ucl_msgpack_parse_map
483 : : },
484 : : {
485 : : 0x90,
486 : : 4,
487 : : msgpack_fixarray,
488 : : 0,
489 : : MSGPACK_FLAG_FIXED|MSGPACK_FLAG_CONTAINER,
490 : : ucl_msgpack_parse_array
491 : : },
492 : : {
493 : : 0xd9,
494 : : 8,
495 : : msgpack_str8,
496 : : 1,
497 : : MSGPACK_FLAG_KEY,
498 : : ucl_msgpack_parse_string
499 : : },
500 : : {
501 : : 0xc4,
502 : : 8,
503 : : msgpack_bin8,
504 : : 1,
505 : : MSGPACK_FLAG_KEY,
506 : : ucl_msgpack_parse_string
507 : : },
508 : : {
509 : : 0xcf,
510 : : 8,
511 : : msgpack_uint64,
512 : : 8,
513 : : MSGPACK_FLAG_FIXED,
514 : : ucl_msgpack_parse_int
515 : : },
516 : : {
517 : : 0xd3,
518 : : 8,
519 : : msgpack_int64,
520 : : 8,
521 : : MSGPACK_FLAG_FIXED,
522 : : ucl_msgpack_parse_int
523 : : },
524 : : {
525 : : 0xce,
526 : : 8,
527 : : msgpack_uint32,
528 : : 4,
529 : : MSGPACK_FLAG_FIXED,
530 : : ucl_msgpack_parse_int
531 : : },
532 : : {
533 : : 0xd2,
534 : : 8,
535 : : msgpack_int32,
536 : : 4,
537 : : MSGPACK_FLAG_FIXED,
538 : : ucl_msgpack_parse_int
539 : : },
540 : : {
541 : : 0xcb,
542 : : 8,
543 : : msgpack_float64,
544 : : 8,
545 : : MSGPACK_FLAG_FIXED,
546 : : ucl_msgpack_parse_float
547 : : },
548 : : {
549 : : 0xca,
550 : : 8,
551 : : msgpack_float32,
552 : : 4,
553 : : MSGPACK_FLAG_FIXED,
554 : : ucl_msgpack_parse_float
555 : : },
556 : : {
557 : : 0xc2,
558 : : 8,
559 : : msgpack_false,
560 : : 1,
561 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
562 : : ucl_msgpack_parse_bool
563 : : },
564 : : {
565 : : 0xc3,
566 : : 8,
567 : : msgpack_true,
568 : : 1,
569 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
570 : : ucl_msgpack_parse_bool
571 : : },
572 : : {
573 : : 0xcc,
574 : : 8,
575 : : msgpack_uint8,
576 : : 1,
577 : : MSGPACK_FLAG_FIXED,
578 : : ucl_msgpack_parse_int
579 : : },
580 : : {
581 : : 0xcd,
582 : : 8,
583 : : msgpack_uint16,
584 : : 2,
585 : : MSGPACK_FLAG_FIXED,
586 : : ucl_msgpack_parse_int
587 : : },
588 : : {
589 : : 0xd0,
590 : : 8,
591 : : msgpack_int8,
592 : : 1,
593 : : MSGPACK_FLAG_FIXED,
594 : : ucl_msgpack_parse_int
595 : : },
596 : : {
597 : : 0xd1,
598 : : 8,
599 : : msgpack_int16,
600 : : 2,
601 : : MSGPACK_FLAG_FIXED,
602 : : ucl_msgpack_parse_int
603 : : },
604 : : {
605 : : 0xc0,
606 : : 8,
607 : : msgpack_nil,
608 : : 0,
609 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
610 : : ucl_msgpack_parse_null
611 : : },
612 : : {
613 : : 0xda,
614 : : 8,
615 : : msgpack_str16,
616 : : 2,
617 : : MSGPACK_FLAG_KEY,
618 : : ucl_msgpack_parse_string
619 : : },
620 : : {
621 : : 0xdb,
622 : : 8,
623 : : msgpack_str32,
624 : : 4,
625 : : MSGPACK_FLAG_KEY,
626 : : ucl_msgpack_parse_string
627 : : },
628 : : {
629 : : 0xc5,
630 : : 8,
631 : : msgpack_bin16,
632 : : 2,
633 : : MSGPACK_FLAG_KEY,
634 : : ucl_msgpack_parse_string
635 : : },
636 : : {
637 : : 0xc6,
638 : : 8,
639 : : msgpack_bin32,
640 : : 4,
641 : : MSGPACK_FLAG_KEY,
642 : : ucl_msgpack_parse_string
643 : : },
644 : : {
645 : : 0xdc,
646 : : 8,
647 : : msgpack_array16,
648 : : 2,
649 : : MSGPACK_FLAG_CONTAINER,
650 : : ucl_msgpack_parse_array
651 : : },
652 : : {
653 : : 0xdd,
654 : : 8,
655 : : msgpack_array32,
656 : : 4,
657 : : MSGPACK_FLAG_CONTAINER,
658 : : ucl_msgpack_parse_array
659 : : },
660 : : {
661 : : 0xde,
662 : : 8,
663 : : msgpack_map16,
664 : : 2,
665 : : MSGPACK_FLAG_CONTAINER|MSGPACK_FLAG_ASSOC,
666 : : ucl_msgpack_parse_map
667 : : },
668 : : {
669 : : 0xdf,
670 : : 8,
671 : : msgpack_map32,
672 : : 4,
673 : : MSGPACK_FLAG_CONTAINER|MSGPACK_FLAG_ASSOC,
674 : : ucl_msgpack_parse_map
675 : : },
676 : : {
677 : : 0xc7,
678 : : 8,
679 : : msgpack_ext8,
680 : : 1,
681 : : MSGPACK_FLAG_EXT,
682 : : ucl_msgpack_parse_ignore
683 : : },
684 : : {
685 : : 0xc8,
686 : : 8,
687 : : msgpack_ext16,
688 : : 2,
689 : : MSGPACK_FLAG_EXT,
690 : : ucl_msgpack_parse_ignore
691 : : },
692 : : {
693 : : 0xc9,
694 : : 8,
695 : : msgpack_ext32,
696 : : 4,
697 : : MSGPACK_FLAG_EXT,
698 : : ucl_msgpack_parse_ignore
699 : : },
700 : : {
701 : : 0xd4,
702 : : 8,
703 : : msgpack_fixext1,
704 : : 1,
705 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
706 : : ucl_msgpack_parse_ignore
707 : : },
708 : : {
709 : : 0xd5,
710 : : 8,
711 : : msgpack_fixext2,
712 : : 2,
713 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
714 : : ucl_msgpack_parse_ignore
715 : : },
716 : : {
717 : : 0xd6,
718 : : 8,
719 : : msgpack_fixext4,
720 : : 4,
721 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
722 : : ucl_msgpack_parse_ignore
723 : : },
724 : : {
725 : : 0xd7,
726 : : 8,
727 : : msgpack_fixext8,
728 : : 8,
729 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
730 : : ucl_msgpack_parse_ignore
731 : : },
732 : : {
733 : : 0xd8,
734 : : 8,
735 : : msgpack_fixext16,
736 : : 16,
737 : : MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
738 : : ucl_msgpack_parse_ignore
739 : : }
740 : : };
741 : :
742 : : #undef MSGPACK_DEBUG_PARSER
743 : :
744 : : static inline struct ucl_msgpack_parser *
745 : 0 : ucl_msgpack_get_parser_from_type (unsigned char t)
746 : : {
747 : : unsigned int i, shift, mask;
748 : :
749 [ # # ]: 0 : for (i = 0; i < sizeof (parsers) / sizeof (parsers[0]); i ++) {
750 : 0 : shift = CHAR_BIT - parsers[i].prefixlen;
751 : 0 : mask = parsers[i].prefix >> shift;
752 : :
753 [ # # ]: 0 : if (mask == (((unsigned int)t) >> shift)) {
754 : 0 : return &parsers[i];
755 : : }
756 : 0 : }
757 : :
758 : 0 : return NULL;
759 : 0 : }
760 : :
761 : : static inline struct ucl_stack *
762 : 0 : ucl_msgpack_get_container (struct ucl_parser *parser,
763 : : struct ucl_msgpack_parser *obj_parser, uint64_t len)
764 : : {
765 : : struct ucl_stack *stack;
766 : :
767 [ # # ]: 0 : assert (obj_parser != NULL);
768 : :
769 [ # # ]: 0 : if (obj_parser->flags & MSGPACK_FLAG_CONTAINER) {
770 : : /*
771 : : * Insert new container to the stack
772 : : */
773 [ # # ]: 0 : if (parser->stack == NULL) {
774 : 0 : parser->stack = calloc (1, sizeof (struct ucl_stack));
775 : :
776 [ # # ]: 0 : if (parser->stack == NULL) {
777 : 0 : ucl_create_err (&parser->err, "no memory");
778 : 0 : return NULL;
779 : : }
780 : :
781 : 0 : parser->stack->chunk = parser->chunks;
782 : 0 : }
783 : : else {
784 : 0 : stack = calloc (1, sizeof (struct ucl_stack));
785 : :
786 [ # # ]: 0 : if (stack == NULL) {
787 : 0 : ucl_create_err (&parser->err, "no memory");
788 : 0 : return NULL;
789 : : }
790 : :
791 : 0 : stack->chunk = parser->chunks;
792 : 0 : stack->next = parser->stack;
793 : 0 : parser->stack = stack;
794 : : }
795 : :
796 : 0 : parser->stack->e.len = len;
797 : :
798 : : #ifdef MSGPACK_DEBUG_PARSER
799 : : stack = parser->stack;
800 : : while (stack) {
801 : : fprintf(stderr, "+");
802 : : stack = stack->next;
803 : : }
804 : :
805 : : fprintf(stderr, "%s -> %d\n", obj_parser->flags & MSGPACK_FLAG_ASSOC ? "object" : "array", (int)len);
806 : : #endif
807 : 0 : }
808 : : else {
809 : : /*
810 : : * Get the current stack top
811 : : */
812 [ # # ]: 0 : if (parser->stack) {
813 : 0 : return parser->stack;
814 : : }
815 : : else {
816 : 0 : ucl_create_err (&parser->err, "bad top level object for msgpack");
817 : 0 : return NULL;
818 : : }
819 : : }
820 : :
821 : 0 : return parser->stack;
822 : 0 : }
823 : :
824 : : static bool
825 : 0 : ucl_msgpack_is_container_finished (struct ucl_stack *container)
826 : : {
827 [ # # ]: 0 : assert (container != NULL);
828 : :
829 : :
830 [ # # ]: 0 : if (container->e.len == 0) {
831 : 0 : return true;
832 : : }
833 : :
834 : 0 : return false;
835 : 0 : }
836 : :
837 : : static bool
838 : 0 : ucl_msgpack_insert_object (struct ucl_parser *parser,
839 : : const unsigned char *key,
840 : : size_t keylen, ucl_object_t *obj)
841 : : {
842 : : struct ucl_stack *container;
843 : :
844 : 0 : container = parser->stack;
845 [ # # ]: 0 : assert (container != NULL);
846 [ # # ]: 0 : assert (container->e.len > 0);
847 [ # # ]: 0 : assert (obj != NULL);
848 [ # # ]: 0 : assert (container->obj != NULL);
849 : :
850 [ # # ]: 0 : if (container->obj->type == UCL_ARRAY) {
851 : 0 : ucl_array_append (container->obj, obj);
852 : 0 : }
853 [ # # ]: 0 : else if (container->obj->type == UCL_OBJECT) {
854 [ # # # # ]: 0 : if (key == NULL || keylen == 0) {
855 : 0 : ucl_create_err (&parser->err, "cannot insert object with no key");
856 : 0 : return false;
857 : : }
858 : :
859 : 0 : obj->key = key;
860 : 0 : obj->keylen = keylen;
861 : :
862 [ # # ]: 0 : if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
863 : 0 : ucl_copy_key_trash (obj);
864 : 0 : }
865 : :
866 : 0 : ucl_parser_process_object_element (parser, obj);
867 : 0 : }
868 : : else {
869 : 0 : ucl_create_err (&parser->err, "bad container type");
870 : 0 : return false;
871 : : }
872 : :
873 : 0 : container->e.len--;
874 : :
875 : 0 : return true;
876 : 0 : }
877 : :
878 : : static struct ucl_stack *
879 : 0 : ucl_msgpack_get_next_container (struct ucl_parser *parser)
880 : : {
881 : 0 : struct ucl_stack *cur = NULL;
882 : : uint64_t len;
883 : :
884 : 0 : cur = parser->stack;
885 : :
886 [ # # ]: 0 : if (cur == NULL) {
887 : 0 : return NULL;
888 : : }
889 : :
890 : 0 : len = cur->e.len;
891 : :
892 [ # # ]: 0 : if (len == 0) {
893 : : /* We need to switch to the previous container */
894 : 0 : parser->stack = cur->next;
895 : 0 : parser->cur_obj = cur->obj;
896 : 0 : free (cur);
897 : :
898 : : #ifdef MSGPACK_DEBUG_PARSER
899 : : cur = parser->stack;
900 : : while (cur) {
901 : : fprintf(stderr, "-");
902 : : cur = cur->next;
903 : : }
904 : : fprintf(stderr, "-%s -> %d\n", parser->cur_obj->type == UCL_OBJECT ? "object" : "array", (int)parser->cur_obj->len);
905 : : #endif
906 : :
907 : 0 : return ucl_msgpack_get_next_container (parser);
908 : : }
909 : :
910 : : /*
911 : : * For UCL containers we don't know length, so we just insert the whole
912 : : * message pack blob into the top level container
913 : : */
914 : :
915 [ # # ]: 0 : assert (cur->obj != NULL);
916 : :
917 : 0 : return cur;
918 : 0 : }
919 : :
920 : : #define CONSUME_RET do { \
921 : : if (ret != -1) { \
922 : : p += ret; \
923 : : remain -= ret; \
924 : : obj_parser = NULL; \
925 : : assert (remain >= 0); \
926 : : } \
927 : : else { \
928 : : ucl_create_err (&parser->err, \
929 : : "cannot parse type %d of len %u", \
930 : : (int)obj_parser->fmt, \
931 : : (unsigned)len); \
932 : : return false; \
933 : : } \
934 : : } while(0)
935 : :
936 : : #define GET_NEXT_STATE do { \
937 : : container = ucl_msgpack_get_next_container (parser); \
938 : : if (container == NULL) { \
939 : : ucl_create_err (&parser->err, \
940 : : "empty container"); \
941 : : return false; \
942 : : } \
943 : : next_state = container->obj->type == UCL_OBJECT ? \
944 : : read_assoc_key : read_array_value; \
945 : : } while(0)
946 : :
947 : : static bool
948 : 0 : ucl_msgpack_consume (struct ucl_parser *parser)
949 : : {
950 : 0 : const unsigned char *p, *end, *key = NULL;
951 : : struct ucl_stack *container;
952 : : enum e_msgpack_parser_state {
953 : : read_type,
954 : : start_assoc,
955 : : start_array,
956 : : read_assoc_key,
957 : : read_assoc_value,
958 : : finish_assoc_value,
959 : : read_array_value,
960 : : finish_array_value,
961 : : error_state
962 : 0 : } state = read_type, next_state = error_state;
963 : 0 : struct ucl_msgpack_parser *obj_parser = NULL;
964 : 0 : uint64_t len = 0;
965 : 0 : ssize_t ret, remain, keylen = 0;
966 : : #ifdef MSGPACK_DEBUG_PARSER
967 : : uint64_t i;
968 : : enum e_msgpack_parser_state hist[256];
969 : : #endif
970 : :
971 : 0 : p = parser->chunks->begin;
972 : 0 : remain = parser->chunks->remain;
973 : 0 : end = p + remain;
974 : :
975 : :
976 [ # # ]: 0 : while (p < end) {
977 : : #ifdef MSGPACK_DEBUG_PARSER
978 : : hist[i++ % 256] = state;
979 : : #endif
980 [ # # # # : 0 : switch (state) {
# # # #
# ]
981 : : case read_type:
982 : 0 : obj_parser = ucl_msgpack_get_parser_from_type (*p);
983 : :
984 [ # # ]: 0 : if (obj_parser == NULL) {
985 : 0 : ucl_create_err (&parser->err, "unknown msgpack format: %x",
986 : 0 : (unsigned int)*p);
987 : :
988 : 0 : return false;
989 : : }
990 : : /* Now check length sanity */
991 [ # # ]: 0 : if (obj_parser->flags & MSGPACK_FLAG_FIXED) {
992 [ # # ]: 0 : if (obj_parser->len == 0) {
993 : : /* We have an embedded size */
994 : 0 : len = *p & ~obj_parser->prefix;
995 : 0 : }
996 : : else {
997 [ # # ]: 0 : if (remain < obj_parser->len) {
998 : 0 : ucl_create_err (&parser->err, "not enough data remain to "
999 : : "read object's length: %u remain, %u needed",
1000 : 0 : (unsigned)remain, obj_parser->len);
1001 : :
1002 : 0 : return false;
1003 : : }
1004 : :
1005 : 0 : len = obj_parser->len;
1006 : : }
1007 : :
1008 [ # # ]: 0 : if (!(obj_parser->flags & MSGPACK_FLAG_TYPEVALUE)) {
1009 : : /* We must pass value as the second byte */
1010 [ # # ]: 0 : if (remain > 0) {
1011 : 0 : p ++;
1012 : 0 : remain --;
1013 : 0 : }
1014 : 0 : }
1015 : : else {
1016 : : /* Len is irrelevant now */
1017 : 0 : len = 0;
1018 : : }
1019 : 0 : }
1020 : : else {
1021 : : /* Length is not embedded */
1022 : 0 : remain --;
1023 : :
1024 [ # # ]: 0 : if (remain < obj_parser->len) {
1025 : 0 : ucl_create_err (&parser->err, "not enough data remain to "
1026 : : "read object's length: %u remain, %u needed",
1027 : 0 : (unsigned)remain, obj_parser->len);
1028 : :
1029 : 0 : return false;
1030 : : }
1031 : :
1032 : 0 : p ++;
1033 : :
1034 [ # # # # : 0 : switch (obj_parser->len) {
# ]
1035 : : case 1:
1036 : 0 : len = *p;
1037 : 0 : break;
1038 : : case 2:
1039 : 0 : len = FROM_BE16 (*(uint16_t *)p);
1040 : 0 : break;
1041 : : case 4:
1042 : 0 : len = FROM_BE32 (*(uint32_t *)p);
1043 : 0 : break;
1044 : : case 8:
1045 : 0 : len = FROM_BE64 (*(uint64_t *)p);
1046 : 0 : break;
1047 : : default:
1048 : 0 : ucl_create_err (&parser->err, "invalid length of the length field: %u",
1049 : 0 : (unsigned)obj_parser->len);
1050 : :
1051 : 0 : return false;
1052 : : }
1053 : :
1054 : 0 : p += obj_parser->len;
1055 : 0 : remain -= obj_parser->len;
1056 : : }
1057 : :
1058 [ # # ]: 0 : if (obj_parser->flags & MSGPACK_FLAG_ASSOC) {
1059 : : /* We have just read the new associative map */
1060 : 0 : state = start_assoc;
1061 : 0 : }
1062 [ # # ]: 0 : else if (obj_parser->flags & MSGPACK_FLAG_CONTAINER){
1063 : 0 : state = start_array;
1064 : 0 : }
1065 : : else {
1066 : 0 : state = next_state;
1067 : : }
1068 : :
1069 : 0 : break;
1070 : : case start_assoc:
1071 : 0 : parser->cur_obj = ucl_object_new_full (UCL_OBJECT,
1072 : 0 : parser->chunks->priority);
1073 : : /* Insert to the previous level container */
1074 [ # # # # : 0 : if (parser->stack && !ucl_msgpack_insert_object (parser,
# # ]
1075 : 0 : key, keylen, parser->cur_obj)) {
1076 : 0 : return false;
1077 : : }
1078 : : /* Get new container */
1079 : 0 : container = ucl_msgpack_get_container (parser, obj_parser, len);
1080 : :
1081 [ # # ]: 0 : if (container == NULL) {
1082 : 0 : return false;
1083 : : }
1084 : :
1085 : 0 : ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1086 : 0 : p, remain);
1087 [ # # # # ]: 0 : CONSUME_RET;
1088 : 0 : key = NULL;
1089 : 0 : keylen = 0;
1090 : :
1091 [ # # ]: 0 : if (len > 0) {
1092 : 0 : state = read_type;
1093 : 0 : next_state = read_assoc_key;
1094 : 0 : }
1095 : : else {
1096 : : /* Empty object */
1097 : 0 : state = finish_assoc_value;
1098 : : }
1099 : 0 : break;
1100 : :
1101 : : case start_array:
1102 : 0 : parser->cur_obj = ucl_object_new_full (UCL_ARRAY,
1103 : 0 : parser->chunks->priority);
1104 : : /* Insert to the previous level container */
1105 [ # # # # : 0 : if (parser->stack && !ucl_msgpack_insert_object (parser,
# # ]
1106 : 0 : key, keylen, parser->cur_obj)) {
1107 : 0 : return false;
1108 : : }
1109 : : /* Get new container */
1110 : 0 : container = ucl_msgpack_get_container (parser, obj_parser, len);
1111 : :
1112 [ # # ]: 0 : if (container == NULL) {
1113 : 0 : return false;
1114 : : }
1115 : :
1116 : 0 : ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1117 : 0 : p, remain);
1118 [ # # # # ]: 0 : CONSUME_RET;
1119 : :
1120 [ # # ]: 0 : if (len > 0) {
1121 : 0 : state = read_type;
1122 : 0 : next_state = read_array_value;
1123 : 0 : }
1124 : : else {
1125 : : /* Empty array */
1126 : 0 : state = finish_array_value;
1127 : : }
1128 : 0 : break;
1129 : :
1130 : : case read_array_value:
1131 : : /*
1132 : : * p is now at the value start, len now contains length read and
1133 : : * obj_parser contains the corresponding specific parser
1134 : : */
1135 : 0 : container = parser->stack;
1136 : :
1137 [ # # ]: 0 : if (parser->stack == NULL) {
1138 : 0 : ucl_create_err (&parser->err,
1139 : : "read assoc value when no container represented");
1140 : 0 : return false;
1141 : : }
1142 : :
1143 : 0 : ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1144 : 0 : p, remain);
1145 [ # # # # ]: 0 : CONSUME_RET;
1146 : :
1147 : :
1148 : : /* Insert value to the container and check if we have finished array */
1149 [ # # # # ]: 0 : if (!ucl_msgpack_insert_object (parser, NULL, 0,
1150 : 0 : parser->cur_obj)) {
1151 : 0 : return false;
1152 : : }
1153 : :
1154 [ # # ]: 0 : if (ucl_msgpack_is_container_finished (container)) {
1155 : 0 : state = finish_array_value;
1156 : 0 : }
1157 : : else {
1158 : : /* Read more elements */
1159 : 0 : state = read_type;
1160 : 0 : next_state = read_array_value;
1161 : : }
1162 : :
1163 : 0 : break;
1164 : :
1165 : : case read_assoc_key:
1166 : : /*
1167 : : * Keys must have string type for ucl msgpack
1168 : : */
1169 [ # # ]: 0 : if (!(obj_parser->flags & MSGPACK_FLAG_KEY)) {
1170 : 0 : ucl_create_err (&parser->err, "bad type for key: %u, expected "
1171 : 0 : "string", (unsigned)obj_parser->fmt);
1172 : :
1173 : 0 : return false;
1174 : : }
1175 : :
1176 : 0 : key = p;
1177 : 0 : keylen = len;
1178 : :
1179 [ # # # # ]: 0 : if (keylen > remain || keylen == 0) {
1180 : 0 : ucl_create_err (&parser->err, "too long or empty key");
1181 : 0 : return false;
1182 : : }
1183 : :
1184 : 0 : p += len;
1185 : 0 : remain -= len;
1186 : :
1187 : 0 : state = read_type;
1188 : 0 : next_state = read_assoc_value;
1189 : 0 : break;
1190 : :
1191 : : case read_assoc_value:
1192 : : /*
1193 : : * p is now at the value start, len now contains length read and
1194 : : * obj_parser contains the corresponding specific parser
1195 : : */
1196 : 0 : container = parser->stack;
1197 : :
1198 [ # # ]: 0 : if (container == NULL) {
1199 : 0 : ucl_create_err (&parser->err,
1200 : : "read assoc value when no container represented");
1201 : 0 : return false;
1202 : : }
1203 : :
1204 : 0 : ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1205 : 0 : p, remain);
1206 [ # # # # ]: 0 : CONSUME_RET;
1207 : :
1208 [ # # ]: 0 : assert (key != NULL && keylen > 0);
1209 : :
1210 [ # # # # ]: 0 : if (!ucl_msgpack_insert_object (parser, key, keylen,
1211 : 0 : parser->cur_obj)) {
1212 : :
1213 : 0 : return false;
1214 : : }
1215 : :
1216 : 0 : key = NULL;
1217 : 0 : keylen = 0;
1218 : :
1219 [ # # ]: 0 : if (ucl_msgpack_is_container_finished (container)) {
1220 : 0 : state = finish_assoc_value;
1221 : 0 : }
1222 : : else {
1223 : : /* Read more elements */
1224 : 0 : state = read_type;
1225 : 0 : next_state = read_assoc_key;
1226 : : }
1227 : 0 : break;
1228 : :
1229 : : case finish_array_value:
1230 : : case finish_assoc_value:
1231 [ # # ]: 0 : GET_NEXT_STATE;
1232 : 0 : state = read_type;
1233 : 0 : break;
1234 : :
1235 : : case error_state:
1236 : 0 : ucl_create_err (&parser->err, "invalid state machine state");
1237 : :
1238 : 0 : return false;
1239 : : }
1240 : : }
1241 : :
1242 : : /* Check the finishing state */
1243 [ # # # # ]: 0 : switch (state) {
1244 : : case start_array:
1245 : : case start_assoc:
1246 : : /* Empty container at the end */
1247 [ # # ]: 0 : if (len != 0) {
1248 : 0 : ucl_create_err (&parser->err,
1249 : : "invalid non-empty container at the end; len=%zu",
1250 : 0 : (uintmax_t)len);
1251 : :
1252 : 0 : return false;
1253 : : }
1254 : :
1255 : 0 : parser->cur_obj = ucl_object_new_full (
1256 : 0 : state == start_array ? UCL_ARRAY : UCL_OBJECT,
1257 : 0 : parser->chunks->priority);
1258 : :
1259 [ # # ]: 0 : if (parser->stack == NULL) {
1260 : 0 : ucl_create_err (&parser->err,
1261 : : "read assoc value when no container represented");
1262 : 0 : return false;
1263 : : }
1264 : : /* Insert to the previous level container */
1265 [ # # # # ]: 0 : if (!ucl_msgpack_insert_object (parser,
1266 : 0 : key, keylen, parser->cur_obj)) {
1267 : 0 : return false;
1268 : : }
1269 : : /* Get new container */
1270 : 0 : container = ucl_msgpack_get_container (parser, obj_parser, len);
1271 : :
1272 [ # # ]: 0 : if (container == NULL) {
1273 : 0 : return false;
1274 : : }
1275 : :
1276 : 0 : ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1277 : 0 : p, remain);
1278 : 0 : break;
1279 : :
1280 : : case read_array_value:
1281 : : case read_assoc_value:
1282 [ # # ]: 0 : if (len != 0) {
1283 : 0 : ucl_create_err (&parser->err, "unfinished value at the end");
1284 : :
1285 : 0 : return false;
1286 : : }
1287 : :
1288 : 0 : container = parser->stack;
1289 : :
1290 [ # # ]: 0 : if (parser->stack == NULL) {
1291 : 0 : ucl_create_err (&parser->err,
1292 : : "read assoc value when no container represented");
1293 : 0 : return false;
1294 : : }
1295 : :
1296 : 0 : ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1297 : 0 : p, remain);
1298 [ # # # # ]: 0 : CONSUME_RET;
1299 : :
1300 : :
1301 : : /* Insert value to the container and check if we have finished array */
1302 [ # # # # ]: 0 : if (!ucl_msgpack_insert_object (parser, NULL, 0,
1303 : 0 : parser->cur_obj)) {
1304 : 0 : return false;
1305 : : }
1306 : 0 : break;
1307 : : case finish_array_value:
1308 : : case finish_assoc_value:
1309 : : case read_type:
1310 : : /* Valid finishing state */
1311 : 0 : break;
1312 : : default:
1313 : : /* Invalid finishing state */
1314 : 0 : ucl_create_err (&parser->err, "invalid state machine finishing state: %d",
1315 : 0 : state);
1316 : :
1317 : 0 : return false;
1318 : : }
1319 : :
1320 : : /* Rewind to the top level container */
1321 : 0 : ucl_msgpack_get_next_container (parser);
1322 : :
1323 [ # # ]: 0 : if (parser->stack != NULL) {
1324 : 0 : ucl_create_err (&parser->err, "incomplete container");
1325 : :
1326 : 0 : return false;
1327 : : }
1328 : :
1329 : 0 : return true;
1330 : 0 : }
1331 : :
1332 : : bool
1333 : 0 : ucl_parse_msgpack (struct ucl_parser *parser)
1334 : : {
1335 : 0 : ucl_object_t *container = NULL;
1336 : : const unsigned char *p;
1337 : : bool ret;
1338 : :
1339 [ # # ]: 0 : assert (parser != NULL);
1340 [ # # ]: 0 : assert (parser->chunks != NULL);
1341 [ # # ]: 0 : assert (parser->chunks->begin != NULL);
1342 [ # # ]: 0 : assert (parser->chunks->remain != 0);
1343 : :
1344 : 0 : p = parser->chunks->begin;
1345 : :
1346 [ # # ]: 0 : if (parser->stack) {
1347 : 0 : container = parser->stack->obj;
1348 : 0 : }
1349 : :
1350 : : /*
1351 : : * When we start parsing message pack chunk, we must ensure that we
1352 : : * have either a valid container or the top object inside message pack is
1353 : : * of container type
1354 : : */
1355 [ # # ]: 0 : if (container == NULL) {
1356 [ # # # # : 0 : if ((*p & 0x80) != 0x80 && !(*p >= 0xdc && *p <= 0xdf)) {
# # ]
1357 : 0 : ucl_create_err (&parser->err, "bad top level object for msgpack");
1358 : 0 : return false;
1359 : : }
1360 : 0 : }
1361 : :
1362 : 0 : ret = ucl_msgpack_consume (parser);
1363 : :
1364 [ # # # # ]: 0 : if (ret && parser->top_obj == NULL) {
1365 : 0 : parser->top_obj = parser->cur_obj;
1366 : 0 : }
1367 : :
1368 : 0 : return ret;
1369 : 0 : }
1370 : :
1371 : : static ssize_t
1372 : 0 : ucl_msgpack_parse_map (struct ucl_parser *parser,
1373 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1374 : : const unsigned char *pos, size_t remain)
1375 : : {
1376 : 0 : container->obj = parser->cur_obj;
1377 : :
1378 : 0 : return 0;
1379 : : }
1380 : :
1381 : : static ssize_t
1382 : 0 : ucl_msgpack_parse_array (struct ucl_parser *parser,
1383 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1384 : : const unsigned char *pos, size_t remain)
1385 : : {
1386 : 0 : container->obj = parser->cur_obj;
1387 : :
1388 : 0 : return 0;
1389 : : }
1390 : :
1391 : : static ssize_t
1392 : 0 : ucl_msgpack_parse_string (struct ucl_parser *parser,
1393 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1394 : : const unsigned char *pos, size_t remain)
1395 : : {
1396 : : ucl_object_t *obj;
1397 : :
1398 [ # # ]: 0 : if (len > remain) {
1399 : 0 : return -1;
1400 : : }
1401 : :
1402 : 0 : obj = ucl_object_new_full (UCL_STRING, parser->chunks->priority);
1403 : 0 : obj->value.sv = pos;
1404 : 0 : obj->len = len;
1405 : :
1406 [ # # # # ]: 0 : if (fmt >= msgpack_bin8 && fmt <= msgpack_bin32) {
1407 : 0 : obj->flags |= UCL_OBJECT_BINARY;
1408 : 0 : }
1409 : :
1410 [ # # ]: 0 : if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
1411 [ # # ]: 0 : if (obj->flags & UCL_OBJECT_BINARY) {
1412 : 0 : obj->trash_stack[UCL_TRASH_VALUE] = malloc (len);
1413 : :
1414 [ # # ]: 0 : if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
1415 : 0 : memcpy (obj->trash_stack[UCL_TRASH_VALUE], pos, len);
1416 : 0 : }
1417 : 0 : }
1418 : : else {
1419 : 0 : ucl_copy_value_trash (obj);
1420 : : }
1421 : 0 : }
1422 : :
1423 : 0 : parser->cur_obj = obj;
1424 : :
1425 : 0 : return len;
1426 : 0 : }
1427 : :
1428 : : static ssize_t
1429 : 0 : ucl_msgpack_parse_int (struct ucl_parser *parser,
1430 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1431 : : const unsigned char *pos, size_t remain)
1432 : : {
1433 : : ucl_object_t *obj;
1434 : : int8_t iv8;
1435 : : int16_t iv16;
1436 : : int32_t iv32;
1437 : : int64_t iv64;
1438 : : uint16_t uiv16;
1439 : : uint32_t uiv32;
1440 : : uint64_t uiv64;
1441 : :
1442 : :
1443 [ # # ]: 0 : if (len > remain) {
1444 : 0 : return -1;
1445 : : }
1446 : :
1447 : 0 : obj = ucl_object_new_full (UCL_INT, parser->chunks->priority);
1448 : :
1449 [ # # # # : 0 : switch (fmt) {
# # # # #
# # ]
1450 : : case msgpack_positive_fixint:
1451 : 0 : obj->value.iv = (*pos & 0x7f);
1452 : 0 : len = 1;
1453 : 0 : break;
1454 : : case msgpack_negative_fixint:
1455 : 0 : obj->value.iv = - (*pos & 0x1f);
1456 : 0 : len = 1;
1457 : 0 : break;
1458 : : case msgpack_uint8:
1459 : 0 : obj->value.iv = (unsigned char)*pos;
1460 : 0 : len = 1;
1461 : 0 : break;
1462 : : case msgpack_int8:
1463 : 0 : memcpy (&iv8, pos, sizeof (iv8));
1464 : 0 : obj->value.iv = iv8;
1465 : 0 : len = 1;
1466 : 0 : break;
1467 : : case msgpack_int16:
1468 : 0 : memcpy (&iv16, pos, sizeof (iv16));
1469 : 0 : iv16 = FROM_BE16 (iv16);
1470 : 0 : obj->value.iv = iv16;
1471 : 0 : len = 2;
1472 : 0 : break;
1473 : : case msgpack_uint16:
1474 : 0 : memcpy (&uiv16, pos, sizeof (uiv16));
1475 : 0 : uiv16 = FROM_BE16 (uiv16);
1476 : 0 : obj->value.iv = uiv16;
1477 : 0 : len = 2;
1478 : 0 : break;
1479 : : case msgpack_int32:
1480 : 0 : memcpy (&iv32, pos, sizeof (iv32));
1481 : 0 : iv32 = FROM_BE32 (iv32);
1482 : 0 : obj->value.iv = iv32;
1483 : 0 : len = 4;
1484 : 0 : break;
1485 : : case msgpack_uint32:
1486 : 0 : memcpy(&uiv32, pos, sizeof(uiv32));
1487 : 0 : uiv32 = FROM_BE32(uiv32);
1488 : 0 : obj->value.iv = uiv32;
1489 : 0 : len = 4;
1490 : 0 : break;
1491 : : case msgpack_int64:
1492 : 0 : memcpy (&iv64, pos, sizeof (iv64));
1493 : 0 : iv64 = FROM_BE64 (iv64);
1494 : 0 : obj->value.iv = iv64;
1495 : 0 : len = 8;
1496 : 0 : break;
1497 : : case msgpack_uint64:
1498 : 0 : memcpy(&uiv64, pos, sizeof(uiv64));
1499 : 0 : uiv64 = FROM_BE64(uiv64);
1500 : 0 : obj->value.iv = uiv64;
1501 : 0 : len = 8;
1502 : 0 : break;
1503 : : default:
1504 : 0 : assert (0);
1505 : : break;
1506 : : }
1507 : :
1508 : 0 : parser->cur_obj = obj;
1509 : :
1510 : 0 : return len;
1511 : 0 : }
1512 : :
1513 : : static ssize_t
1514 : 0 : ucl_msgpack_parse_float (struct ucl_parser *parser,
1515 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1516 : : const unsigned char *pos, size_t remain)
1517 : : {
1518 : : ucl_object_t *obj;
1519 : : union {
1520 : : uint32_t i;
1521 : : float f;
1522 : : } d;
1523 : : uint64_t uiv64;
1524 : :
1525 [ # # ]: 0 : if (len > remain) {
1526 : 0 : return -1;
1527 : : }
1528 : :
1529 : 0 : obj = ucl_object_new_full (UCL_FLOAT, parser->chunks->priority);
1530 : :
1531 [ # # # ]: 0 : switch (fmt) {
1532 : : case msgpack_float32:
1533 : 0 : memcpy(&d.i, pos, sizeof(d.i));
1534 : 0 : d.i = FROM_BE32(d.i);
1535 : : /* XXX: can be slow */
1536 : 0 : obj->value.dv = d.f;
1537 : 0 : len = 4;
1538 : 0 : break;
1539 : : case msgpack_float64:
1540 : 0 : memcpy(&uiv64, pos, sizeof(uiv64));
1541 : 0 : uiv64 = FROM_BE64(uiv64);
1542 : 0 : obj->value.iv = uiv64;
1543 : 0 : len = 8;
1544 : 0 : break;
1545 : : default:
1546 : 0 : assert (0);
1547 : : break;
1548 : : }
1549 : :
1550 : 0 : parser->cur_obj = obj;
1551 : :
1552 : 0 : return len;
1553 : 0 : }
1554 : :
1555 : : static ssize_t
1556 : 0 : ucl_msgpack_parse_bool (struct ucl_parser *parser,
1557 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1558 : : const unsigned char *pos, size_t remain)
1559 : : {
1560 : : ucl_object_t *obj;
1561 : :
1562 [ # # ]: 0 : if (len > remain) {
1563 : 0 : return -1;
1564 : : }
1565 : :
1566 : 0 : obj = ucl_object_new_full (UCL_BOOLEAN, parser->chunks->priority);
1567 : :
1568 [ # # # ]: 0 : switch (fmt) {
1569 : : case msgpack_true:
1570 : 0 : obj->value.iv = true;
1571 : 0 : break;
1572 : : case msgpack_false:
1573 : 0 : obj->value.iv = false;
1574 : 0 : break;
1575 : : default:
1576 : 0 : assert (0);
1577 : : break;
1578 : : }
1579 : :
1580 : 0 : parser->cur_obj = obj;
1581 : :
1582 : 0 : return 1;
1583 : 0 : }
1584 : :
1585 : : static ssize_t
1586 : 0 : ucl_msgpack_parse_null (struct ucl_parser *parser,
1587 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1588 : : const unsigned char *pos, size_t remain)
1589 : : {
1590 : : ucl_object_t *obj;
1591 : :
1592 [ # # ]: 0 : if (len > remain) {
1593 : 0 : return -1;
1594 : : }
1595 : :
1596 : 0 : obj = ucl_object_new_full (UCL_NULL, parser->chunks->priority);
1597 : 0 : parser->cur_obj = obj;
1598 : :
1599 : 0 : return 1;
1600 : 0 : }
1601 : :
1602 : : static ssize_t
1603 : 0 : ucl_msgpack_parse_ignore (struct ucl_parser *parser,
1604 : : struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
1605 : : const unsigned char *pos, size_t remain)
1606 : : {
1607 [ # # ]: 0 : if (len > remain) {
1608 : 0 : return -1;
1609 : : }
1610 : :
1611 [ # # # # : 0 : switch (fmt) {
# # # ]
1612 : : case msgpack_fixext1:
1613 : 0 : len = 2;
1614 : 0 : break;
1615 : : case msgpack_fixext2:
1616 : 0 : len = 3;
1617 : 0 : break;
1618 : : case msgpack_fixext4:
1619 : 0 : len = 5;
1620 : 0 : break;
1621 : : case msgpack_fixext8:
1622 : 0 : len = 9;
1623 : 0 : break;
1624 : : case msgpack_fixext16:
1625 : 0 : len = 17;
1626 : 0 : break;
1627 : : case msgpack_ext8:
1628 : : case msgpack_ext16:
1629 : : case msgpack_ext32:
1630 : 0 : len = len + 1;
1631 : 0 : break;
1632 : : default:
1633 : 0 : ucl_create_err (&parser->err, "bad type: %x", (unsigned)fmt);
1634 : 0 : return -1;
1635 : : }
1636 : :
1637 : 0 : return len;
1638 : 0 : }
|