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