]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libucl/src/ucl_msgpack.c
Fix build post a0409676120c1e558d0ade943019934e0f15118d.
[FreeBSD/FreeBSD.git] / contrib / libucl / src / ucl_msgpack.c
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 ucl_emitter_print_int_msgpack (struct ucl_emitter_context *ctx, int64_t val)
102 {
103         const struct ucl_emitter_functions *func = ctx->func;
104         unsigned char buf[sizeof(uint64_t) + 1];
105         const unsigned char mask_positive = 0x7f, mask_negative = 0xe0,
106                 uint8_ch = 0xcc, uint16_ch = 0xcd, uint32_ch = 0xce, uint64_ch = 0xcf,
107                 int8_ch = 0xd0, int16_ch = 0xd1, int32_ch = 0xd2, int64_ch = 0xd3;
108         unsigned len;
109
110         if (val >= 0) {
111                 if (val <= 0x7f) {
112                         /* Fixed num 7 bits */
113                         len = 1;
114                         buf[0] = mask_positive & val;
115                 }
116                 else if (val <= UINT8_MAX) {
117                         len = 2;
118                         buf[0] = uint8_ch;
119                         buf[1] = val & 0xff;
120                 }
121                 else if (val <= UINT16_MAX) {
122                         uint16_t v = TO_BE16 (val);
123
124                         len = 3;
125                         buf[0] = uint16_ch;
126                         memcpy (&buf[1], &v, sizeof (v));
127                 }
128                 else if (val <= UINT32_MAX) {
129                         uint32_t v = TO_BE32 (val);
130
131                         len = 5;
132                         buf[0] = uint32_ch;
133                         memcpy (&buf[1], &v, sizeof (v));
134                 }
135                 else {
136                         uint64_t v = TO_BE64 (val);
137
138                         len = 9;
139                         buf[0] = uint64_ch;
140                         memcpy (&buf[1], &v, sizeof (v));
141                 }
142         }
143         else {
144                 uint64_t uval;
145                 /* Bithack abs */
146                 uval = ((val ^ (val >> 63)) - (val >> 63));
147
148                 if (val > -(1 << 5)) {
149                         len = 1;
150                         buf[0] = (mask_negative | uval) & 0xff;
151                 }
152                 else if (uval <= INT8_MAX) {
153                         uint8_t v = (uint8_t)val;
154                         len = 2;
155                         buf[0] = int8_ch;
156                         buf[1] = v;
157                 }
158                 else if (uval <= INT16_MAX) {
159                         uint16_t v = TO_BE16 (val);
160
161                         len = 3;
162                         buf[0] = int16_ch;
163                         memcpy (&buf[1], &v, sizeof (v));
164                 }
165                 else if (uval <= INT32_MAX) {
166                         uint32_t v = TO_BE32 (val);
167
168                         len = 5;
169                         buf[0] = int32_ch;
170                         memcpy (&buf[1], &v, sizeof (v));
171                 }
172                 else {
173                         uint64_t v = TO_BE64 (val);
174
175                         len = 9;
176                         buf[0] = int64_ch;
177                         memcpy (&buf[1], &v, sizeof (v));
178                 }
179         }
180
181         func->ucl_emitter_append_len (buf, len, func->ud);
182 }
183
184 void
185 ucl_emitter_print_double_msgpack (struct ucl_emitter_context *ctx, double val)
186 {
187         const struct ucl_emitter_functions *func = ctx->func;
188         union {
189                 double d;
190                 uint64_t i;
191         } u;
192         const unsigned char dbl_ch = 0xcb;
193         unsigned char buf[sizeof(double) + 1];
194
195         /* Convert to big endian */
196         u.d = val;
197         u.i = TO_BE64 (u.i);
198
199         buf[0] = dbl_ch;
200         memcpy (&buf[1], &u.d, sizeof (double));
201         func->ucl_emitter_append_len (buf, sizeof (buf), func->ud);
202 }
203
204 void
205 ucl_emitter_print_bool_msgpack (struct ucl_emitter_context *ctx, bool val)
206 {
207         const struct ucl_emitter_functions *func = ctx->func;
208         const unsigned char true_ch = 0xc3, false_ch = 0xc2;
209
210         func->ucl_emitter_append_character (val ? true_ch : false_ch, 1, func->ud);
211 }
212
213 void
214 ucl_emitter_print_string_msgpack (struct ucl_emitter_context *ctx,
215                 const char *s, size_t len)
216 {
217         const struct ucl_emitter_functions *func = ctx->func;
218         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         if (len <= 0x1F) {
223                 blen = 1;
224                 buf[0] = (len | fix_mask) & 0xff;
225         }
226         else if (len <= 0xff) {
227                 blen = 2;
228                 buf[0] = l8_ch;
229                 buf[1] = len & 0xff;
230         }
231         else if (len <= 0xffff) {
232                 uint16_t bl = TO_BE16 (len);
233
234                 blen = 3;
235                 buf[0] = l16_ch;
236                 memcpy (&buf[1], &bl, sizeof (bl));
237         }
238         else {
239                 uint32_t bl = TO_BE32 (len);
240
241                 blen = 5;
242                 buf[0] = l32_ch;
243                 memcpy (&buf[1], &bl, sizeof (bl));
244         }
245
246         func->ucl_emitter_append_len (buf, blen, func->ud);
247         func->ucl_emitter_append_len (s, len, func->ud);
248 }
249
250 void
251 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
284 ucl_emitter_print_null_msgpack (struct ucl_emitter_context *ctx)
285 {
286         const struct ucl_emitter_functions *func = ctx->func;
287         const unsigned char nil = 0xc0;
288
289         func->ucl_emitter_append_character (nil, 1, func->ud);
290 }
291
292 void
293 ucl_emitter_print_key_msgpack (bool print_key, struct ucl_emitter_context *ctx,
294                 const ucl_object_t *obj)
295 {
296         if (print_key) {
297                 ucl_emitter_print_string_msgpack (ctx, obj->key, obj->keylen);
298         }
299 }
300
301 void
302 ucl_emitter_print_array_msgpack (struct ucl_emitter_context *ctx, size_t len)
303 {
304         const struct ucl_emitter_functions *func = ctx->func;
305         const unsigned char fix_mask = 0x90, l16_ch = 0xdc, l32_ch = 0xdd;
306         unsigned char buf[5];
307         unsigned blen;
308
309         if (len <= 0xF) {
310                 blen = 1;
311                 buf[0] = (len | fix_mask) & 0xff;
312         }
313         else if (len <= 0xffff) {
314                 uint16_t bl = TO_BE16 (len);
315
316                 blen = 3;
317                 buf[0] = l16_ch;
318                 memcpy (&buf[1], &bl, sizeof (bl));
319         }
320         else {
321                 uint32_t bl = TO_BE32 (len);
322
323                 blen = 5;
324                 buf[0] = l32_ch;
325                 memcpy (&buf[1], &bl, sizeof (bl));
326         }
327
328         func->ucl_emitter_append_len (buf, blen, func->ud);
329 }
330
331 void
332 ucl_emitter_print_object_msgpack (struct ucl_emitter_context *ctx, size_t len)
333 {
334         const struct ucl_emitter_functions *func = ctx->func;
335         const unsigned char fix_mask = 0x80, l16_ch = 0xde, l32_ch = 0xdf;
336         unsigned char buf[5];
337         unsigned blen;
338
339         if (len <= 0xF) {
340                 blen = 1;
341                 buf[0] = (len | fix_mask) & 0xff;
342         }
343         else if (len <= 0xffff) {
344                 uint16_t bl = TO_BE16 (len);
345
346                 blen = 3;
347                 buf[0] = l16_ch;
348                 memcpy (&buf[1], &bl, sizeof (bl));
349         }
350         else {
351                 uint32_t bl = TO_BE32 (len);
352
353                 blen = 5;
354                 buf[0] = l32_ch;
355                 memcpy (&buf[1], &bl, sizeof (bl));
356         }
357
358         func->ucl_emitter_append_len (buf, blen, func->ud);
359 }
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 ucl_msgpack_get_parser_from_type (unsigned char t)
746 {
747         unsigned int i, shift, mask;
748
749         for (i = 0; i < sizeof (parsers) / sizeof (parsers[0]); i ++) {
750                 shift = CHAR_BIT - parsers[i].prefixlen;
751                 mask = parsers[i].prefix >> shift;
752
753                 if (mask == (((unsigned int)t) >> shift)) {
754                         return &parsers[i];
755                 }
756         }
757
758         return NULL;
759 }
760
761 static inline struct ucl_stack *
762 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         assert (obj_parser != NULL);
768
769         if (obj_parser->flags & MSGPACK_FLAG_CONTAINER) {
770                 /*
771                  * Insert new container to the stack
772                  */
773                 if (parser->stack == NULL) {
774                         parser->stack = calloc (1, sizeof (struct ucl_stack));
775
776                         if (parser->stack == NULL) {
777                                 ucl_create_err (&parser->err, "no memory");
778                                 return NULL;
779                         }
780
781                         parser->stack->chunk = parser->chunks;
782                 }
783                 else {
784                         stack = calloc (1, sizeof (struct ucl_stack));
785
786                         if (stack == NULL) {
787                                 ucl_create_err (&parser->err, "no memory");
788                                 return NULL;
789                         }
790
791                         stack->chunk = parser->chunks;
792                         stack->next = parser->stack;
793                         parser->stack = stack;
794                 }
795
796                 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         }
808         else {
809                 /*
810                  * Get the current stack top
811                  */
812                 if (parser->stack) {
813                         return parser->stack;
814                 }
815                 else {
816                         ucl_create_err (&parser->err, "bad top level object for msgpack");
817                         return NULL;
818                 }
819         }
820
821         return parser->stack;
822 }
823
824 static bool
825 ucl_msgpack_is_container_finished (struct ucl_stack *container)
826 {
827         assert (container != NULL);
828
829
830         if (container->e.len == 0) {
831                 return true;
832         }
833
834         return false;
835 }
836
837 static bool
838 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         container = parser->stack;
845         assert (container != NULL);
846         assert (container->e.len > 0);
847         assert (obj != NULL);
848         assert (container->obj != NULL);
849
850         if (container->obj->type == UCL_ARRAY) {
851                 ucl_array_append (container->obj, obj);
852         }
853         else if (container->obj->type == UCL_OBJECT) {
854                 if (key == NULL || keylen == 0) {
855                         ucl_create_err (&parser->err, "cannot insert object with no key");
856                         return false;
857                 }
858
859                 obj->key = key;
860                 obj->keylen = keylen;
861
862                 if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
863                         ucl_copy_key_trash (obj);
864                 }
865
866                 ucl_parser_process_object_element (parser, obj);
867         }
868         else {
869                 ucl_create_err (&parser->err, "bad container type");
870                 return false;
871         }
872
873         container->e.len--;
874
875         return true;
876 }
877
878 static struct ucl_stack *
879 ucl_msgpack_get_next_container (struct ucl_parser *parser)
880 {
881         struct ucl_stack *cur = NULL;
882         uint64_t len;
883
884         cur = parser->stack;
885
886         if (cur == NULL) {
887                 return NULL;
888         }
889
890         len = cur->e.len;
891
892         if (len == 0) {
893                 /* We need to switch to the previous container */
894                 parser->stack = cur->next;
895                 parser->cur_obj = cur->obj;
896                 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                 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         assert (cur->obj != NULL);
916
917         return cur;
918 }
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 ucl_msgpack_consume (struct ucl_parser *parser)
949 {
950         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         } state = read_type, next_state = error_state;
963         struct ucl_msgpack_parser *obj_parser = NULL;
964         uint64_t len = 0;
965         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         p = parser->chunks->begin;
972         remain = parser->chunks->remain;
973         end = p + remain;
974
975
976         while (p < end) {
977 #ifdef MSGPACK_DEBUG_PARSER
978                 hist[i++ % 256] = state;
979 #endif
980                 switch (state) {
981                 case read_type:
982                         obj_parser = ucl_msgpack_get_parser_from_type (*p);
983
984                         if (obj_parser == NULL) {
985                                 ucl_create_err (&parser->err, "unknown msgpack format: %x",
986                                                 (unsigned int)*p);
987
988                                 return false;
989                         }
990                         /* Now check length sanity */
991                         if (obj_parser->flags & MSGPACK_FLAG_FIXED) {
992                                 if (obj_parser->len == 0) {
993                                         /* We have an embedded size */
994                                         len = *p & ~obj_parser->prefix;
995                                 }
996                                 else {
997                                         if (remain < obj_parser->len) {
998                                                 ucl_create_err (&parser->err, "not enough data remain to "
999                                                                 "read object's length: %u remain, %u needed",
1000                                                                 (unsigned)remain, obj_parser->len);
1001
1002                                                 return false;
1003                                         }
1004
1005                                         len = obj_parser->len;
1006                                 }
1007
1008                                 if (!(obj_parser->flags & MSGPACK_FLAG_TYPEVALUE)) {
1009                                         /* We must pass value as the second byte */
1010                                         if (remain > 0) {
1011                                                 p ++;
1012                                                 remain --;
1013                                         }
1014                                 }
1015                                 else {
1016                                         /* Len is irrelevant now */
1017                                         len = 0;
1018                                 }
1019                         }
1020                         else {
1021                                 /* Length is not embedded */
1022                                 remain --;
1023
1024                                 if (remain < obj_parser->len) {
1025                                         ucl_create_err (&parser->err, "not enough data remain to "
1026                                                         "read object's length: %u remain, %u needed",
1027                                                         (unsigned)remain, obj_parser->len);
1028
1029                                         return false;
1030                                 }
1031
1032                                 p ++;
1033
1034                                 switch (obj_parser->len) {
1035                                 case 1:
1036                                         len = *p;
1037                                         break;
1038                                 case 2:
1039                                         len = FROM_BE16 (*(uint16_t *)p);
1040                                         break;
1041                                 case 4:
1042                                         len = FROM_BE32 (*(uint32_t *)p);
1043                                         break;
1044                                 case 8:
1045                                         len = FROM_BE64 (*(uint64_t *)p);
1046                                         break;
1047                                 default:
1048                                         ucl_create_err (&parser->err, "invalid length of the length field: %u",
1049                                                         (unsigned)obj_parser->len);
1050
1051                                         return false;
1052                                 }
1053
1054                                 p += obj_parser->len;
1055                                 remain -= obj_parser->len;
1056                         }
1057
1058                         if (obj_parser->flags & MSGPACK_FLAG_ASSOC) {
1059                                 /* We have just read the new associative map */
1060                                 state = start_assoc;
1061                         }
1062                         else if (obj_parser->flags & MSGPACK_FLAG_CONTAINER){
1063                                 state = start_array;
1064                         }
1065                         else {
1066                                 state = next_state;
1067                         }
1068
1069                         break;
1070                 case start_assoc:
1071                         parser->cur_obj = ucl_object_new_full (UCL_OBJECT,
1072                                         parser->chunks->priority);
1073                         /* Insert to the previous level container */
1074                         if (parser->stack && !ucl_msgpack_insert_object (parser,
1075                                         key, keylen, parser->cur_obj)) {
1076                                 return false;
1077                         }
1078                         /* Get new container */
1079                         container = ucl_msgpack_get_container (parser, obj_parser, len);
1080
1081                         if (container == NULL) {
1082                                 return false;
1083                         }
1084
1085                         ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1086                                         p, remain);
1087                         CONSUME_RET;
1088                         key = NULL;
1089                         keylen = 0;
1090
1091                         if (len > 0) {
1092                                 state = read_type;
1093                                 next_state = read_assoc_key;
1094                         }
1095                         else {
1096                                 /* Empty object */
1097                                 state = finish_assoc_value;
1098                         }
1099                         break;
1100
1101                 case start_array:
1102                         parser->cur_obj = ucl_object_new_full (UCL_ARRAY,
1103                                         parser->chunks->priority);
1104                         /* Insert to the previous level container */
1105                         if (parser->stack && !ucl_msgpack_insert_object (parser,
1106                                         key, keylen, parser->cur_obj)) {
1107                                 return false;
1108                         }
1109                         /* Get new container */
1110                         container = ucl_msgpack_get_container (parser, obj_parser, len);
1111
1112                         if (container == NULL) {
1113                                 return false;
1114                         }
1115
1116                         ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1117                                                                 p, remain);
1118                         CONSUME_RET;
1119
1120                         if (len > 0) {
1121                                 state = read_type;
1122                                 next_state = read_array_value;
1123                         }
1124                         else {
1125                                 /* Empty array */
1126                                 state = finish_array_value;
1127                         }
1128                         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                         container = parser->stack;
1136
1137                         if (parser->stack == NULL) {
1138                                 ucl_create_err (&parser->err,
1139                                                 "read assoc value when no container represented");
1140                                 return false;
1141                         }
1142
1143                         ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1144                                         p, remain);
1145                         CONSUME_RET;
1146
1147
1148                         /* Insert value to the container and check if we have finished array */
1149                         if (!ucl_msgpack_insert_object (parser, NULL, 0,
1150                                         parser->cur_obj)) {
1151                                 return false;
1152                         }
1153
1154                         if (ucl_msgpack_is_container_finished (container)) {
1155                                 state = finish_array_value;
1156                         }
1157                         else {
1158                                 /* Read more elements */
1159                                 state = read_type;
1160                                 next_state = read_array_value;
1161                         }
1162
1163                         break;
1164
1165                 case read_assoc_key:
1166                         /*
1167                          * Keys must have string type for ucl msgpack
1168                          */
1169                         if (!(obj_parser->flags & MSGPACK_FLAG_KEY)) {
1170                                 ucl_create_err (&parser->err, "bad type for key: %u, expected "
1171                                                 "string", (unsigned)obj_parser->fmt);
1172
1173                                 return false;
1174                         }
1175
1176                         key = p;
1177                         keylen = len;
1178
1179                         if (keylen > remain || keylen == 0) {
1180                                 ucl_create_err (&parser->err, "too long or empty key");
1181                                 return false;
1182                         }
1183
1184                         p += len;
1185                         remain -= len;
1186
1187                         state = read_type;
1188                         next_state = read_assoc_value;
1189                         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                         container = parser->stack;
1197
1198                         if (container == NULL) {
1199                                 ucl_create_err (&parser->err,
1200                                                 "read assoc value when no container represented");
1201                                 return false;
1202                         }
1203
1204                         ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1205                                         p, remain);
1206                         CONSUME_RET;
1207
1208                         assert (key != NULL && keylen > 0);
1209
1210                         if (!ucl_msgpack_insert_object (parser, key, keylen,
1211                                         parser->cur_obj)) {
1212
1213                                 return false;
1214                         }
1215
1216                         key = NULL;
1217                         keylen = 0;
1218
1219                         if (ucl_msgpack_is_container_finished (container)) {
1220                                 state = finish_assoc_value;
1221                         }
1222                         else {
1223                                 /* Read more elements */
1224                                 state = read_type;
1225                                 next_state = read_assoc_key;
1226                         }
1227                         break;
1228
1229                 case finish_array_value:
1230                 case finish_assoc_value:
1231                         GET_NEXT_STATE;
1232                         state = read_type;
1233                         break;
1234
1235                 case error_state:
1236                         ucl_create_err (&parser->err, "invalid state machine state");
1237
1238                         return false;
1239                 }
1240         }
1241
1242         /* Check the finishing state */
1243         switch (state) {
1244         case start_array:
1245         case start_assoc:
1246                 /* Empty container at the end */
1247                 if (len != 0) {
1248                         ucl_create_err (&parser->err,
1249                                         "invalid non-empty container at the end; len=%zu",
1250                                         (size_t)len);
1251
1252                         return false;
1253                 }
1254
1255                 parser->cur_obj = ucl_object_new_full (
1256                                 state == start_array ? UCL_ARRAY : UCL_OBJECT,
1257                                 parser->chunks->priority);
1258
1259                 if (parser->stack == NULL) {
1260                         ucl_create_err (&parser->err,
1261                                         "read assoc value when no container represented");
1262                         return false;
1263                 }
1264                 /* Insert to the previous level container */
1265                 if (!ucl_msgpack_insert_object (parser,
1266                                 key, keylen, parser->cur_obj)) {
1267                         return false;
1268                 }
1269                 /* Get new container */
1270                 container = ucl_msgpack_get_container (parser, obj_parser, len);
1271
1272                 if (container == NULL) {
1273                         return false;
1274                 }
1275
1276                 ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1277                                 p, remain);
1278                 break;
1279
1280         case read_array_value:
1281         case read_assoc_value:
1282                 if (len != 0) {
1283                         ucl_create_err (&parser->err, "unfinished value at the end");
1284
1285                         return false;
1286                 }
1287
1288                 container = parser->stack;
1289
1290                 if (parser->stack == NULL) {
1291                         ucl_create_err (&parser->err,
1292                                         "read assoc value when no container represented");
1293                         return false;
1294                 }
1295
1296                 ret = obj_parser->func (parser, container, len, obj_parser->fmt,
1297                                 p, remain);
1298                 CONSUME_RET;
1299
1300
1301                 /* Insert value to the container and check if we have finished array */
1302                 if (!ucl_msgpack_insert_object (parser, NULL, 0,
1303                                 parser->cur_obj)) {
1304                         return false;
1305                 }
1306                 break;
1307         case finish_array_value:
1308         case finish_assoc_value:
1309         case read_type:
1310                 /* Valid finishing state */
1311                 break;
1312         default:
1313                 /* Invalid finishing state */
1314                 ucl_create_err (&parser->err, "invalid state machine finishing state: %d",
1315                                 state);
1316
1317                 return false;
1318         }
1319
1320         /* Rewind to the top level container */
1321         ucl_msgpack_get_next_container (parser);
1322
1323         if (parser->stack != NULL) {
1324                 ucl_create_err (&parser->err, "incomplete container");
1325
1326                 return false;
1327         }
1328
1329         return true;
1330 }
1331
1332 bool
1333 ucl_parse_msgpack (struct ucl_parser *parser)
1334 {
1335         ucl_object_t *container = NULL;
1336         const unsigned char *p;
1337         bool ret;
1338
1339         assert (parser != NULL);
1340         assert (parser->chunks != NULL);
1341         assert (parser->chunks->begin != NULL);
1342         assert (parser->chunks->remain != 0);
1343
1344         p = parser->chunks->begin;
1345
1346         if (parser->stack) {
1347                 container = parser->stack->obj;
1348         }
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         if (container == NULL) {
1356                 if ((*p & 0x80) != 0x80 && !(*p >= 0xdc && *p <= 0xdf)) {
1357                         ucl_create_err (&parser->err, "bad top level object for msgpack");
1358                         return false;
1359                 }
1360         }
1361
1362         ret = ucl_msgpack_consume (parser);
1363
1364         if (ret && parser->top_obj == NULL) {
1365                 parser->top_obj = parser->cur_obj;
1366         }
1367
1368         return ret;
1369 }
1370
1371 static ssize_t
1372 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         container->obj = parser->cur_obj;
1377
1378         return 0;
1379 }
1380
1381 static ssize_t
1382 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         container->obj = parser->cur_obj;
1387
1388         return 0;
1389 }
1390
1391 static ssize_t
1392 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         if (len > remain) {
1399                 return -1;
1400         }
1401
1402         obj = ucl_object_new_full (UCL_STRING, parser->chunks->priority);
1403         obj->value.sv = pos;
1404         obj->len = len;
1405
1406         if (fmt >= msgpack_bin8 && fmt <= msgpack_bin32) {
1407                 obj->flags |= UCL_OBJECT_BINARY;
1408         }
1409
1410         if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
1411                 if (obj->flags & UCL_OBJECT_BINARY) {
1412                         obj->trash_stack[UCL_TRASH_VALUE] = malloc (len);
1413
1414                         if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
1415                                 memcpy (obj->trash_stack[UCL_TRASH_VALUE], pos, len);
1416                         }
1417                 }
1418                 else {
1419                         ucl_copy_value_trash (obj);
1420                 }
1421         }
1422
1423         parser->cur_obj = obj;
1424
1425         return len;
1426 }
1427
1428 static ssize_t
1429 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         if (len > remain) {
1444                 return -1;
1445         }
1446
1447         obj = ucl_object_new_full (UCL_INT, parser->chunks->priority);
1448
1449         switch (fmt) {
1450         case msgpack_positive_fixint:
1451                 obj->value.iv = (*pos & 0x7f);
1452                 len = 1;
1453                 break;
1454         case msgpack_negative_fixint:
1455                 obj->value.iv = - (*pos & 0x1f);
1456                 len = 1;
1457                 break;
1458         case msgpack_uint8:
1459                 obj->value.iv = (unsigned char)*pos;
1460                 len = 1;
1461                 break;
1462         case msgpack_int8:
1463                 memcpy (&iv8, pos, sizeof (iv8));
1464                 obj->value.iv = iv8;
1465                 len = 1;
1466                 break;
1467         case msgpack_int16:
1468                 memcpy (&iv16, pos, sizeof (iv16));
1469                 iv16 = FROM_BE16 (iv16);
1470                 obj->value.iv = iv16;
1471                 len = 2;
1472                 break;
1473         case msgpack_uint16:
1474                 memcpy (&uiv16, pos, sizeof (uiv16));
1475                 uiv16 = FROM_BE16 (uiv16);
1476                 obj->value.iv = uiv16;
1477                 len = 2;
1478                 break;
1479         case msgpack_int32:
1480                 memcpy (&iv32, pos, sizeof (iv32));
1481                 iv32 = FROM_BE32 (iv32);
1482                 obj->value.iv = iv32;
1483                 len = 4;
1484                 break;
1485         case msgpack_uint32:
1486                 memcpy(&uiv32, pos, sizeof(uiv32));
1487                 uiv32 = FROM_BE32(uiv32);
1488                 obj->value.iv = uiv32;
1489                 len = 4;
1490                 break;
1491         case msgpack_int64:
1492                 memcpy (&iv64, pos, sizeof (iv64));
1493                 iv64 = FROM_BE64 (iv64);
1494                 obj->value.iv = iv64;
1495                 len = 8;
1496                 break;
1497         case msgpack_uint64:
1498                 memcpy(&uiv64, pos, sizeof(uiv64));
1499                 uiv64 = FROM_BE64(uiv64);
1500                 obj->value.iv = uiv64;
1501                 len = 8;
1502                 break;
1503         default:
1504                 assert (0);
1505                 break;
1506         }
1507
1508         parser->cur_obj = obj;
1509
1510         return len;
1511 }
1512
1513 static ssize_t
1514 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         if (len > remain) {
1526                 return -1;
1527         }
1528
1529         obj = ucl_object_new_full (UCL_FLOAT, parser->chunks->priority);
1530
1531         switch (fmt) {
1532         case msgpack_float32:
1533                 memcpy(&d.i, pos, sizeof(d.i));
1534                 d.i = FROM_BE32(d.i);
1535                 /* XXX: can be slow */
1536                 obj->value.dv = d.f;
1537                 len = 4;
1538                 break;
1539         case msgpack_float64:
1540                 memcpy(&uiv64, pos, sizeof(uiv64));
1541                 uiv64 = FROM_BE64(uiv64);
1542                 obj->value.iv = uiv64;
1543                 len = 8;
1544                 break;
1545         default:
1546                 assert (0);
1547                 break;
1548         }
1549
1550         parser->cur_obj = obj;
1551
1552         return len;
1553 }
1554
1555 static ssize_t
1556 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         if (len > remain) {
1563                 return -1;
1564         }
1565
1566         obj = ucl_object_new_full (UCL_BOOLEAN, parser->chunks->priority);
1567
1568         switch (fmt) {
1569         case msgpack_true:
1570                 obj->value.iv = true;
1571                 break;
1572         case msgpack_false:
1573                 obj->value.iv = false;
1574                 break;
1575         default:
1576                 assert (0);
1577                 break;
1578         }
1579
1580         parser->cur_obj = obj;
1581
1582         return 1;
1583 }
1584
1585 static ssize_t
1586 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         if (len > remain) {
1593                 return -1;
1594         }
1595
1596         obj = ucl_object_new_full (UCL_NULL, parser->chunks->priority);
1597         parser->cur_obj = obj;
1598
1599         return 1;
1600 }
1601
1602 static ssize_t
1603 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         if (len > remain) {
1608                 return -1;
1609         }
1610
1611         switch (fmt) {
1612         case msgpack_fixext1:
1613                 len = 2;
1614                 break;
1615         case msgpack_fixext2:
1616                 len = 3;
1617                 break;
1618         case msgpack_fixext4:
1619                 len = 5;
1620                 break;
1621         case msgpack_fixext8:
1622                 len = 9;
1623                 break;
1624         case msgpack_fixext16:
1625                 len = 17;
1626                 break;
1627         case msgpack_ext8:
1628         case msgpack_ext16:
1629         case msgpack_ext32:
1630                 len = len + 1;
1631                 break;
1632         default:
1633                 ucl_create_err (&parser->err, "bad type: %x", (unsigned)fmt);
1634                 return -1;
1635         }
1636
1637         return len;
1638 }