1 #include <stdbool.h>
2 #include <stddef.h>
3 #include <stdint.h>
4 
5 #include "cmp.h"
6 
7 static const uint32_t version = 10;
8 static const uint32_t mp_version = 5;
9 
10 enum {
11   POSITIVE_FIXNUM_MARKER = 0x00,
12   FIXMAP_MARKER          = 0x80,
13   FIXARRAY_MARKER        = 0x90,
14   FIXSTR_MARKER          = 0xA0,
15   NIL_MARKER             = 0xC0,
16   FALSE_MARKER           = 0xC2,
17   TRUE_MARKER            = 0xC3,
18   BIN8_MARKER            = 0xC4,
19   BIN16_MARKER           = 0xC5,
20   BIN32_MARKER           = 0xC6,
21   EXT8_MARKER            = 0xC7,
22   EXT16_MARKER           = 0xC8,
23   EXT32_MARKER           = 0xC9,
24   FLOAT_MARKER           = 0xCA,
25   DOUBLE_MARKER          = 0xCB,
26   U8_MARKER              = 0xCC,
27   U16_MARKER             = 0xCD,
28   U32_MARKER             = 0xCE,
29   U64_MARKER             = 0xCF,
30   S8_MARKER              = 0xD0,
31   S16_MARKER             = 0xD1,
32   S32_MARKER             = 0xD2,
33   S64_MARKER             = 0xD3,
34   FIXEXT1_MARKER         = 0xD4,
35   FIXEXT2_MARKER         = 0xD5,
36   FIXEXT4_MARKER         = 0xD6,
37   FIXEXT8_MARKER         = 0xD7,
38   FIXEXT16_MARKER        = 0xD8,
39   STR8_MARKER            = 0xD9,
40   STR16_MARKER           = 0xDA,
41   STR32_MARKER           = 0xDB,
42   ARRAY16_MARKER         = 0xDC,
43   ARRAY32_MARKER         = 0xDD,
44   MAP16_MARKER           = 0xDE,
45   MAP32_MARKER           = 0xDF,
46   NEGATIVE_FIXNUM_MARKER = 0xE0
47 };
48 
49 enum {
50   FIXARRAY_SIZE        = 0xF,
51   FIXMAP_SIZE          = 0xF,
52   FIXSTR_SIZE          = 0x1F
53 };
54 
55 enum {
56   ERROR_NONE,
57   STR_DATA_LENGTH_TOO_LONG_ERROR,
58   BIN_DATA_LENGTH_TOO_LONG_ERROR,
59   ARRAY_LENGTH_TOO_LONG_ERROR,
60   MAP_LENGTH_TOO_LONG_ERROR,
61   INPUT_VALUE_TOO_LARGE_ERROR,
62   FIXED_VALUE_WRITING_ERROR,
63   TYPE_MARKER_READING_ERROR,
64   TYPE_MARKER_WRITING_ERROR,
65   DATA_READING_ERROR,
66   DATA_WRITING_ERROR,
67   EXT_TYPE_READING_ERROR,
68   EXT_TYPE_WRITING_ERROR,
69   INVALID_TYPE_ERROR,
70   LENGTH_READING_ERROR,
71   LENGTH_WRITING_ERROR,
72   ERROR_MAX
73 };
74 
75 const char *cmp_error_messages[ERROR_MAX + 1] = {
76   "No Error",
77   "Specified string data length is too long (> 0xFFFFFFFF)",
78   "Specified binary data length is too long (> 0xFFFFFFFF)",
79   "Specified array length is too long (> 0xFFFFFFFF)",
80   "Specified map length is too long (> 0xFFFFFFFF)",
81   "Input value is too large",
82   "Error writing fixed value",
83   "Error reading type marker",
84   "Error writing type marker",
85   "Error reading packed data",
86   "Error writing packed data",
87   "Error reading ext type",
88   "Error writing ext type",
89   "Invalid type",
90   "Error reading size",
91   "Error writing size",
92   "Max Error"
93 };
94 
95 static const int32_t _i = 1;
96 #define is_bigendian() ((*(char *)&_i) == 0)
97 
be16(uint16_t x)98 static uint16_t be16(uint16_t x) {
99   char *b = (char *)&x;
100 
101   if (!is_bigendian()) {
102     char swap = 0;
103 
104     swap = b[0];
105     b[0] = b[1];
106     b[1] = swap;
107   }
108 
109   return x;
110 }
111 
be32(uint32_t x)112 static uint32_t be32(uint32_t x) {
113   char *b = (char *)&x;
114 
115   if (!is_bigendian()) {
116     char swap = 0;
117 
118     swap = b[0];
119     b[0] = b[3];
120     b[3] = swap;
121 
122     swap = b[1];
123     b[1] = b[2];
124     b[2] = swap;
125   }
126 
127   return x;
128 }
129 
be64(uint64_t x)130 static uint64_t be64(uint64_t x) {
131   char *b = (char *)&x;
132 
133   if (!is_bigendian()) {
134     char swap = 0;
135 
136     swap = b[0];
137     b[0] = b[7];
138     b[7] = swap;
139 
140     swap = b[1];
141     b[1] = b[6];
142     b[6] = swap;
143 
144     swap = b[2];
145     b[2] = b[5];
146     b[5] = swap;
147 
148     swap = b[3];
149     b[3] = b[4];
150     b[4] = swap;
151   }
152 
153   return x;
154 }
155 
befloat(float x)156 static float befloat(float x) {
157   char *b = (char *)&x;
158 
159   if (!is_bigendian()) {
160     char swap = 0;
161 
162     swap = b[0];
163     b[0] = b[3];
164     b[3] = swap;
165 
166     swap = b[1];
167     b[1] = b[2];
168     b[2] = swap;
169   }
170 
171   return x;
172 }
173 
bedouble(double x)174 static double bedouble(double x) {
175   char *b = (char *)&x;
176 
177   if (!is_bigendian()) {
178     char swap = 0;
179 
180     swap = b[0];
181     b[0] = b[7];
182     b[7] = swap;
183 
184     swap = b[1];
185     b[1] = b[6];
186     b[6] = swap;
187 
188     swap = b[2];
189     b[2] = b[5];
190     b[5] = swap;
191 
192     swap = b[3];
193     b[3] = b[4];
194     b[4] = swap;
195   }
196 
197   return x;
198 }
199 
read_byte(cmp_ctx_t * ctx,uint8_t * x)200 static bool read_byte(cmp_ctx_t *ctx, uint8_t *x) {
201   return ctx->read(ctx, x, sizeof(uint8_t));
202 }
203 
write_byte(cmp_ctx_t * ctx,uint8_t x)204 static bool write_byte(cmp_ctx_t *ctx, uint8_t x) {
205   return (ctx->write(ctx, &x, sizeof(uint8_t)) == (sizeof(uint8_t)));
206 }
207 
read_type_marker(cmp_ctx_t * ctx,uint8_t * marker)208 static bool read_type_marker(cmp_ctx_t *ctx, uint8_t *marker) {
209   if (read_byte(ctx, marker))
210     return true;
211 
212   ctx->error = TYPE_MARKER_READING_ERROR;
213   return false;
214 }
215 
write_type_marker(cmp_ctx_t * ctx,uint8_t marker)216 static bool write_type_marker(cmp_ctx_t *ctx, uint8_t marker) {
217   if (write_byte(ctx, marker))
218     return true;
219 
220   ctx->error = TYPE_MARKER_WRITING_ERROR;
221   return false;
222 }
223 
write_fixed_value(cmp_ctx_t * ctx,uint8_t value)224 static bool write_fixed_value(cmp_ctx_t *ctx, uint8_t value) {
225   if (write_byte(ctx, value))
226     return true;
227 
228   ctx->error = FIXED_VALUE_WRITING_ERROR;
229   return false;
230 }
231 
cmp_init(cmp_ctx_t * ctx,void * buf,cmp_reader read,cmp_writer write)232 void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read, cmp_writer write) {
233   ctx->error = ERROR_NONE;
234   ctx->buf = buf;
235   ctx->read = read;
236   ctx->write = write;
237 }
238 
cmp_version(void)239 uint32_t cmp_version(void) {
240   return version;
241 }
242 
cmp_mp_version(void)243 uint32_t cmp_mp_version(void) {
244   return mp_version;
245 }
246 
cmp_strerror(cmp_ctx_t * ctx)247 const char* cmp_strerror(cmp_ctx_t *ctx) {
248   if (ctx->error > ERROR_NONE && ctx->error < ERROR_MAX)
249     return cmp_error_messages[ctx->error];
250 
251   return "";
252 }
253 
cmp_write_pfix(cmp_ctx_t * ctx,uint8_t c)254 bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c) {
255   if (c <= 0x7F)
256     return write_fixed_value(ctx, c);
257 
258   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
259   return false;
260 }
261 
cmp_write_nfix(cmp_ctx_t * ctx,int8_t c)262 bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) {
263   if (c >= -32 && c <= -1)
264     return write_fixed_value(ctx, c);
265 
266   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
267   return false;
268 }
269 
cmp_write_sfix(cmp_ctx_t * ctx,int8_t c)270 bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c) {
271   if (c >= 0)
272     return cmp_write_pfix(ctx, c);
273   if (c >= -32 && c <= -1)
274     return cmp_write_nfix(ctx, c);
275 
276   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
277   return false;
278 }
279 
cmp_write_s8(cmp_ctx_t * ctx,int8_t c)280 bool cmp_write_s8(cmp_ctx_t *ctx, int8_t c) {
281   if (!write_type_marker(ctx, S8_MARKER))
282     return false;
283 
284   return ctx->write(ctx, &c, sizeof(int8_t));
285 }
286 
cmp_write_s16(cmp_ctx_t * ctx,int16_t s)287 bool cmp_write_s16(cmp_ctx_t *ctx, int16_t s) {
288   if (!write_type_marker(ctx, S16_MARKER))
289     return false;
290 
291   s = be16(s);
292 
293   return ctx->write(ctx, &s, sizeof(int16_t));
294 }
295 
cmp_write_s32(cmp_ctx_t * ctx,int32_t i)296 bool cmp_write_s32(cmp_ctx_t *ctx, int32_t i) {
297   if (!write_type_marker(ctx, S32_MARKER))
298     return false;
299 
300   i = be32(i);
301 
302   return ctx->write(ctx, &i, sizeof(int32_t));
303 }
304 
cmp_write_s64(cmp_ctx_t * ctx,int64_t l)305 bool cmp_write_s64(cmp_ctx_t *ctx, int64_t l) {
306   if (!write_type_marker(ctx, S64_MARKER))
307     return false;
308 
309   l = be64(l);
310 
311   return ctx->write(ctx, &l, sizeof(int64_t));
312 }
313 
cmp_write_sint(cmp_ctx_t * ctx,int64_t d)314 bool cmp_write_sint(cmp_ctx_t *ctx, int64_t d) {
315   if (d >= 0)
316     return cmp_write_uint(ctx, d);
317   if (d >= -32)
318     return cmp_write_nfix(ctx, d);
319   if (d >= -128)
320     return cmp_write_s8(ctx, d);
321   if (d >= -32768)
322     return cmp_write_s16(ctx, d);
323   if (d >= (-2147483647 - 1))
324     return cmp_write_s32(ctx, d);
325 
326   return cmp_write_s64(ctx, d);
327 }
328 
cmp_write_ufix(cmp_ctx_t * ctx,uint8_t c)329 bool cmp_write_ufix(cmp_ctx_t *ctx, uint8_t c) {
330   return cmp_write_pfix(ctx, c);
331 }
332 
cmp_write_u8(cmp_ctx_t * ctx,uint8_t c)333 bool cmp_write_u8(cmp_ctx_t *ctx, uint8_t c) {
334   if (!write_type_marker(ctx, U8_MARKER))
335     return false;
336 
337   return ctx->write(ctx, &c, sizeof(uint8_t));
338 }
339 
cmp_write_u16(cmp_ctx_t * ctx,uint16_t s)340 bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s) {
341   if (!write_type_marker(ctx, U16_MARKER))
342     return false;
343 
344   s = be16(s);
345 
346   return ctx->write(ctx, &s, sizeof(uint16_t));
347 }
348 
cmp_write_u32(cmp_ctx_t * ctx,uint32_t i)349 bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i) {
350   if (!write_type_marker(ctx, U32_MARKER))
351     return false;
352 
353   i = be32(i);
354 
355   return ctx->write(ctx, &i, sizeof(uint32_t));
356 }
357 
cmp_write_u64(cmp_ctx_t * ctx,uint64_t l)358 bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l) {
359   if (!write_type_marker(ctx, U64_MARKER))
360     return false;
361 
362   l = be64(l);
363 
364   return ctx->write(ctx, &l, sizeof(uint64_t));
365 }
366 
cmp_write_uint(cmp_ctx_t * ctx,uint64_t u)367 bool cmp_write_uint(cmp_ctx_t *ctx, uint64_t u) {
368   if (u <= 0x7F)
369     return cmp_write_pfix(ctx, u);
370   if (u <= 0xFF)
371     return cmp_write_u8(ctx, u);
372   if (u <= 0xFFFF)
373     return cmp_write_u16(ctx, u);
374   if (u <= 0xFFFFFFFF)
375     return cmp_write_u32(ctx, u);
376 
377   return cmp_write_u64(ctx, u);
378 }
379 
cmp_write_float(cmp_ctx_t * ctx,float f)380 bool cmp_write_float(cmp_ctx_t *ctx, float f) {
381   if (!write_type_marker(ctx, FLOAT_MARKER))
382     return false;
383 
384   f = befloat(f);
385 
386   return ctx->write(ctx, &f, sizeof(float));
387 }
388 
cmp_write_double(cmp_ctx_t * ctx,double d)389 bool cmp_write_double(cmp_ctx_t *ctx, double d) {
390   if (!write_type_marker(ctx, DOUBLE_MARKER))
391     return false;
392 
393   d = bedouble(d);
394 
395   return ctx->write(ctx, &d, sizeof(double));
396 }
397 
cmp_write_nil(cmp_ctx_t * ctx)398 bool cmp_write_nil(cmp_ctx_t *ctx) {
399   return write_type_marker(ctx, NIL_MARKER);
400 }
401 
cmp_write_true(cmp_ctx_t * ctx)402 bool cmp_write_true(cmp_ctx_t *ctx) {
403   return write_type_marker(ctx, TRUE_MARKER);
404 }
405 
cmp_write_false(cmp_ctx_t * ctx)406 bool cmp_write_false(cmp_ctx_t *ctx) {
407   return write_type_marker(ctx, FALSE_MARKER);
408 }
409 
cmp_write_bool(cmp_ctx_t * ctx,bool b)410 bool cmp_write_bool(cmp_ctx_t *ctx, bool b) {
411   if (b)
412     return cmp_write_true(ctx);
413 
414   return cmp_write_false(ctx);
415 }
416 
cmp_write_u8_as_bool(cmp_ctx_t * ctx,uint8_t b)417 bool cmp_write_u8_as_bool(cmp_ctx_t *ctx, uint8_t b) {
418   if (b)
419     return cmp_write_true(ctx);
420 
421   return cmp_write_false(ctx);
422 }
423 
cmp_write_fixstr_marker(cmp_ctx_t * ctx,uint8_t size)424 bool cmp_write_fixstr_marker(cmp_ctx_t *ctx, uint8_t size) {
425   if (size <= FIXSTR_SIZE)
426     return write_fixed_value(ctx, FIXSTR_MARKER | size);
427 
428   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
429   return false;
430 }
431 
cmp_write_fixstr(cmp_ctx_t * ctx,const char * data,uint8_t size)432 bool cmp_write_fixstr(cmp_ctx_t *ctx, const char *data, uint8_t size) {
433   if (!cmp_write_fixstr_marker(ctx, size))
434     return false;
435 
436   if (size == 0)
437     return true;
438 
439   if (ctx->write(ctx, data, size))
440     return true;
441 
442   ctx->error = DATA_WRITING_ERROR;
443   return false;
444 }
445 
cmp_write_str8_marker(cmp_ctx_t * ctx,uint8_t size)446 bool cmp_write_str8_marker(cmp_ctx_t *ctx, uint8_t size) {
447   if (!write_type_marker(ctx, STR8_MARKER))
448     return false;
449 
450   if (ctx->write(ctx, &size, sizeof(uint8_t)))
451     return true;
452 
453   ctx->error = LENGTH_WRITING_ERROR;
454   return false;
455 }
456 
cmp_write_str8(cmp_ctx_t * ctx,const char * data,uint8_t size)457 bool cmp_write_str8(cmp_ctx_t *ctx, const char *data, uint8_t size) {
458   if (!cmp_write_str8_marker(ctx, size))
459     return false;
460 
461   if (size == 0)
462     return true;
463 
464   if (ctx->write(ctx, data, size))
465     return true;
466 
467   ctx->error = DATA_WRITING_ERROR;
468   return false;
469 }
470 
cmp_write_str16_marker(cmp_ctx_t * ctx,uint16_t size)471 bool cmp_write_str16_marker(cmp_ctx_t *ctx, uint16_t size) {
472   if (!write_type_marker(ctx, STR16_MARKER))
473     return false;
474 
475   size = be16(size);
476 
477   if (ctx->write(ctx, &size, sizeof(uint16_t)))
478     return true;
479 
480   ctx->error = LENGTH_WRITING_ERROR;
481   return false;
482 }
483 
cmp_write_str16(cmp_ctx_t * ctx,const char * data,uint16_t size)484 bool cmp_write_str16(cmp_ctx_t *ctx, const char *data, uint16_t size) {
485   if (!cmp_write_str16_marker(ctx, size))
486     return false;
487 
488   if (size == 0)
489     return true;
490 
491   if (ctx->write(ctx, data, size))
492     return true;
493 
494   ctx->error = DATA_WRITING_ERROR;
495   return false;
496 }
497 
cmp_write_str32_marker(cmp_ctx_t * ctx,uint32_t size)498 bool cmp_write_str32_marker(cmp_ctx_t *ctx, uint32_t size) {
499   if (!write_type_marker(ctx, STR32_MARKER))
500     return false;
501 
502   size = be32(size);
503 
504   if (ctx->write(ctx, &size, sizeof(uint32_t)))
505     return true;
506 
507   ctx->error = LENGTH_WRITING_ERROR;
508   return false;
509 }
510 
cmp_write_str32(cmp_ctx_t * ctx,const char * data,uint32_t size)511 bool cmp_write_str32(cmp_ctx_t *ctx, const char *data, uint32_t size) {
512   if (!cmp_write_str32_marker(ctx, size))
513     return false;
514 
515   if (size == 0)
516     return true;
517 
518   if (ctx->write(ctx, data, size))
519     return true;
520 
521   ctx->error = DATA_WRITING_ERROR;
522   return false;
523 }
524 
cmp_write_str_marker(cmp_ctx_t * ctx,uint32_t size)525 bool cmp_write_str_marker(cmp_ctx_t *ctx, uint32_t size) {
526   if (size <= FIXSTR_SIZE)
527     return cmp_write_fixstr_marker(ctx, size);
528   if (size <= 0xFF)
529     return cmp_write_str8_marker(ctx, size);
530   if (size <= 0xFFFF)
531     return cmp_write_str16_marker(ctx, size);
532 
533   return cmp_write_str32_marker(ctx, size);
534 }
535 
cmp_write_str(cmp_ctx_t * ctx,const char * data,uint32_t size)536 bool cmp_write_str(cmp_ctx_t *ctx, const char *data, uint32_t size) {
537   if (size <= FIXSTR_SIZE)
538     return cmp_write_fixstr(ctx, data, size);
539   if (size <= 0xFF)
540     return cmp_write_str8(ctx, data, size);
541   if (size <= 0xFFFF)
542     return cmp_write_str16(ctx, data, size);
543 
544   return cmp_write_str32(ctx, data, size);
545 }
546 
cmp_write_bin8_marker(cmp_ctx_t * ctx,uint8_t size)547 bool cmp_write_bin8_marker(cmp_ctx_t *ctx, uint8_t size) {
548   if (!write_type_marker(ctx, BIN8_MARKER))
549     return false;
550 
551   if (ctx->write(ctx, &size, sizeof(uint8_t)))
552     return true;
553 
554   ctx->error = LENGTH_WRITING_ERROR;
555   return false;
556 }
557 
cmp_write_bin8(cmp_ctx_t * ctx,const void * data,uint8_t size)558 bool cmp_write_bin8(cmp_ctx_t *ctx, const void *data, uint8_t size) {
559   if (!cmp_write_bin8_marker(ctx, size))
560     return false;
561 
562   if (size == 0)
563     return true;
564 
565   if (ctx->write(ctx, data, size))
566     return true;
567 
568   ctx->error = DATA_WRITING_ERROR;
569   return false;
570 }
571 
cmp_write_bin16_marker(cmp_ctx_t * ctx,uint16_t size)572 bool cmp_write_bin16_marker(cmp_ctx_t *ctx, uint16_t size) {
573   if (!write_type_marker(ctx, BIN16_MARKER))
574     return false;
575 
576   size = be16(size);
577 
578   if (ctx->write(ctx, &size, sizeof(uint16_t)))
579     return true;
580 
581   ctx->error = LENGTH_WRITING_ERROR;
582   return false;
583 }
584 
cmp_write_bin16(cmp_ctx_t * ctx,const void * data,uint16_t size)585 bool cmp_write_bin16(cmp_ctx_t *ctx, const void *data, uint16_t size) {
586   if (!cmp_write_bin16_marker(ctx, size))
587     return false;
588 
589   if (size == 0)
590     return true;
591 
592   if (ctx->write(ctx, data, size))
593     return true;
594 
595   ctx->error = DATA_WRITING_ERROR;
596   return false;
597 }
598 
cmp_write_bin32_marker(cmp_ctx_t * ctx,uint32_t size)599 bool cmp_write_bin32_marker(cmp_ctx_t *ctx, uint32_t size) {
600   if (!write_type_marker(ctx, BIN32_MARKER))
601     return false;
602 
603   size = be32(size);
604 
605   if (ctx->write(ctx, &size, sizeof(uint32_t)))
606     return true;
607 
608   ctx->error = LENGTH_WRITING_ERROR;
609   return false;
610 }
611 
cmp_write_bin32(cmp_ctx_t * ctx,const void * data,uint32_t size)612 bool cmp_write_bin32(cmp_ctx_t *ctx, const void *data, uint32_t size) {
613   if (!cmp_write_bin32_marker(ctx, size))
614     return false;
615 
616   if (size == 0)
617     return true;
618 
619   if (ctx->write(ctx, data, size))
620     return true;
621 
622   ctx->error = DATA_WRITING_ERROR;
623   return false;
624 }
625 
cmp_write_bin_marker(cmp_ctx_t * ctx,uint32_t size)626 bool cmp_write_bin_marker(cmp_ctx_t *ctx, uint32_t size) {
627   if (size <= 0xFF)
628     return cmp_write_bin8_marker(ctx, size);
629   if (size <= 0xFFFF)
630     return cmp_write_bin16_marker(ctx, size);
631 
632   return cmp_write_bin32_marker(ctx, size);
633 }
634 
cmp_write_bin(cmp_ctx_t * ctx,const void * data,uint32_t size)635 bool cmp_write_bin(cmp_ctx_t *ctx, const void *data, uint32_t size) {
636   if (size <= 0xFF)
637     return cmp_write_bin8(ctx, data, size);
638   if (size <= 0xFFFF)
639     return cmp_write_bin16(ctx, data, size);
640 
641   return cmp_write_bin32(ctx, data, size);
642 }
643 
cmp_write_fixarray(cmp_ctx_t * ctx,uint8_t size)644 bool cmp_write_fixarray(cmp_ctx_t *ctx, uint8_t size) {
645   if (size <= FIXARRAY_SIZE)
646     return write_fixed_value(ctx, FIXARRAY_MARKER | size);
647 
648   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
649   return false;
650 }
651 
cmp_write_array16(cmp_ctx_t * ctx,uint16_t size)652 bool cmp_write_array16(cmp_ctx_t *ctx, uint16_t size) {
653   if (!write_type_marker(ctx, ARRAY16_MARKER))
654     return false;
655 
656   size = be16(size);
657 
658   if (ctx->write(ctx, &size, sizeof(uint16_t)))
659     return true;
660 
661   ctx->error = LENGTH_WRITING_ERROR;
662   return false;
663 }
664 
cmp_write_array32(cmp_ctx_t * ctx,uint32_t size)665 bool cmp_write_array32(cmp_ctx_t *ctx, uint32_t size) {
666   if (!write_type_marker(ctx, ARRAY32_MARKER))
667     return false;
668 
669   size = be32(size);
670 
671   if (ctx->write(ctx, &size, sizeof(uint32_t)))
672     return true;
673 
674   ctx->error = LENGTH_WRITING_ERROR;
675   return false;
676 }
677 
cmp_write_array(cmp_ctx_t * ctx,uint32_t size)678 bool cmp_write_array(cmp_ctx_t *ctx, uint32_t size) {
679   if (size <= FIXARRAY_SIZE)
680     return cmp_write_fixarray(ctx, size);
681   if (size <= 0xFFFF)
682     return cmp_write_array16(ctx, size);
683 
684   return cmp_write_array32(ctx, size);
685 }
686 
cmp_write_fixmap(cmp_ctx_t * ctx,uint8_t size)687 bool cmp_write_fixmap(cmp_ctx_t *ctx, uint8_t size) {
688   if (size <= FIXMAP_SIZE)
689     return write_fixed_value(ctx, FIXMAP_MARKER | size);
690 
691   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
692   return false;
693 }
694 
cmp_write_map16(cmp_ctx_t * ctx,uint16_t size)695 bool cmp_write_map16(cmp_ctx_t *ctx, uint16_t size) {
696   if (!write_type_marker(ctx, MAP16_MARKER))
697     return false;
698 
699   size = be16(size);
700 
701   if (ctx->write(ctx, &size, sizeof(uint16_t)))
702     return true;
703 
704   ctx->error = LENGTH_WRITING_ERROR;
705   return false;
706 }
707 
cmp_write_map32(cmp_ctx_t * ctx,uint32_t size)708 bool cmp_write_map32(cmp_ctx_t *ctx, uint32_t size) {
709   if (!write_type_marker(ctx, MAP32_MARKER))
710     return false;
711 
712   size = be32(size);
713 
714   if (ctx->write(ctx, &size, sizeof(uint32_t)))
715     return true;
716 
717   ctx->error = LENGTH_WRITING_ERROR;
718   return false;
719 }
720 
cmp_write_map(cmp_ctx_t * ctx,uint32_t size)721 bool cmp_write_map(cmp_ctx_t *ctx, uint32_t size) {
722   if (size <= FIXMAP_SIZE)
723     return cmp_write_fixmap(ctx, size);
724   if (size <= 0xFFFF)
725     return cmp_write_map16(ctx, size);
726 
727   return cmp_write_map32(ctx, size);
728 }
729 
cmp_write_fixext1_marker(cmp_ctx_t * ctx,int8_t type)730 bool cmp_write_fixext1_marker(cmp_ctx_t *ctx, int8_t type) {
731   if (!write_type_marker(ctx, FIXEXT1_MARKER))
732     return false;
733 
734   if (ctx->write(ctx, &type, sizeof(int8_t)))
735     return true;
736 
737   ctx->error = EXT_TYPE_WRITING_ERROR;
738   return false;
739 }
740 
cmp_write_fixext1(cmp_ctx_t * ctx,int8_t type,const void * data)741 bool cmp_write_fixext1(cmp_ctx_t *ctx, int8_t type, const void *data) {
742   if (!cmp_write_fixext1_marker(ctx, type))
743     return false;
744 
745   if (ctx->write(ctx, data, 1))
746     return true;
747 
748   ctx->error = DATA_WRITING_ERROR;
749   return false;
750 }
751 
cmp_write_fixext2_marker(cmp_ctx_t * ctx,int8_t type)752 bool cmp_write_fixext2_marker(cmp_ctx_t *ctx, int8_t type) {
753   if (!write_type_marker(ctx, FIXEXT2_MARKER))
754     return false;
755 
756   if (ctx->write(ctx, &type, sizeof(int8_t)))
757     return true;
758 
759   ctx->error = EXT_TYPE_WRITING_ERROR;
760   return false;
761 }
762 
cmp_write_fixext2(cmp_ctx_t * ctx,int8_t type,const void * data)763 bool cmp_write_fixext2(cmp_ctx_t *ctx, int8_t type, const void *data) {
764   if (!cmp_write_fixext2_marker(ctx, type))
765     return false;
766 
767   if (ctx->write(ctx, data, 2))
768     return true;
769 
770   ctx->error = DATA_WRITING_ERROR;
771   return false;
772 }
773 
cmp_write_fixext4_marker(cmp_ctx_t * ctx,int8_t type)774 bool cmp_write_fixext4_marker(cmp_ctx_t *ctx, int8_t type) {
775   if (!write_type_marker(ctx, FIXEXT4_MARKER))
776     return false;
777 
778   if (ctx->write(ctx, &type, sizeof(int8_t)))
779     return true;
780 
781   ctx->error = EXT_TYPE_WRITING_ERROR;
782   return false;
783 }
784 
cmp_write_fixext4(cmp_ctx_t * ctx,int8_t type,const void * data)785 bool cmp_write_fixext4(cmp_ctx_t *ctx, int8_t type, const void *data) {
786   if (!cmp_write_fixext4_marker(ctx, type))
787     return false;
788 
789   if (ctx->write(ctx, data, 4))
790     return true;
791 
792   ctx->error = DATA_WRITING_ERROR;
793   return false;
794 }
795 
cmp_write_fixext8_marker(cmp_ctx_t * ctx,int8_t type)796 bool cmp_write_fixext8_marker(cmp_ctx_t *ctx, int8_t type) {
797   if (!write_type_marker(ctx, FIXEXT8_MARKER))
798     return false;
799 
800   if (ctx->write(ctx, &type, sizeof(int8_t)))
801     return true;
802 
803   ctx->error = EXT_TYPE_WRITING_ERROR;
804   return false;
805 }
806 
cmp_write_fixext8(cmp_ctx_t * ctx,int8_t type,const void * data)807 bool cmp_write_fixext8(cmp_ctx_t *ctx, int8_t type, const void *data) {
808   if (!cmp_write_fixext8_marker(ctx, type))
809     return false;
810 
811   if (ctx->write(ctx, data, 8))
812     return true;
813 
814   ctx->error = DATA_WRITING_ERROR;
815   return false;
816 }
817 
cmp_write_fixext16_marker(cmp_ctx_t * ctx,int8_t type)818 bool cmp_write_fixext16_marker(cmp_ctx_t *ctx, int8_t type) {
819   if (!write_type_marker(ctx, FIXEXT16_MARKER))
820     return false;
821 
822   if (ctx->write(ctx, &type, sizeof(int8_t)))
823     return true;
824 
825   ctx->error = EXT_TYPE_WRITING_ERROR;
826   return false;
827 }
828 
cmp_write_fixext16(cmp_ctx_t * ctx,int8_t type,const void * data)829 bool cmp_write_fixext16(cmp_ctx_t *ctx, int8_t type, const void *data) {
830   if (!cmp_write_fixext16_marker(ctx, type))
831     return false;
832 
833   if (ctx->write(ctx, data, 16))
834     return true;
835 
836   ctx->error = DATA_WRITING_ERROR;
837   return false;
838 }
839 
cmp_write_ext8_marker(cmp_ctx_t * ctx,int8_t type,uint8_t size)840 bool cmp_write_ext8_marker(cmp_ctx_t *ctx, int8_t type, uint8_t size) {
841   if (!write_type_marker(ctx, EXT8_MARKER))
842     return false;
843 
844   if (!ctx->write(ctx, &size, sizeof(uint8_t))) {
845     ctx->error = LENGTH_WRITING_ERROR;
846     return false;
847   }
848 
849   if (ctx->write(ctx, &type, sizeof(int8_t)))
850     return true;
851 
852   ctx->error = EXT_TYPE_WRITING_ERROR;
853   return false;
854 }
855 
cmp_write_ext8(cmp_ctx_t * ctx,int8_t tp,uint8_t sz,const void * data)856 bool cmp_write_ext8(cmp_ctx_t *ctx, int8_t tp, uint8_t sz, const void *data) {
857   if (!cmp_write_ext8_marker(ctx, tp, sz))
858     return false;
859 
860   if (ctx->write(ctx, data, sz))
861     return true;
862 
863   ctx->error = DATA_WRITING_ERROR;
864   return false;
865 }
866 
cmp_write_ext16_marker(cmp_ctx_t * ctx,int8_t type,uint16_t size)867 bool cmp_write_ext16_marker(cmp_ctx_t *ctx, int8_t type, uint16_t size) {
868   if (!write_type_marker(ctx, EXT16_MARKER))
869     return false;
870 
871   size = be16(size);
872 
873   if (!ctx->write(ctx, &size, sizeof(uint16_t))) {
874     ctx->error = LENGTH_WRITING_ERROR;
875     return false;
876   }
877 
878   if (ctx->write(ctx, &type, sizeof(int8_t)))
879     return true;
880 
881   ctx->error = EXT_TYPE_WRITING_ERROR;
882   return false;
883 }
884 
cmp_write_ext16(cmp_ctx_t * ctx,int8_t tp,uint16_t sz,const void * data)885 bool cmp_write_ext16(cmp_ctx_t *ctx, int8_t tp, uint16_t sz, const void *data) {
886   if (!cmp_write_ext16_marker(ctx, tp, sz))
887     return false;
888 
889   if (ctx->write(ctx, data, sz))
890     return true;
891 
892   ctx->error = DATA_WRITING_ERROR;
893   return false;
894 }
895 
cmp_write_ext32_marker(cmp_ctx_t * ctx,int8_t type,uint32_t size)896 bool cmp_write_ext32_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size) {
897   if (!write_type_marker(ctx, EXT32_MARKER))
898     return false;
899 
900   size = be32(size);
901 
902   if (!ctx->write(ctx, &size, sizeof(uint32_t))) {
903     ctx->error = LENGTH_WRITING_ERROR;
904     return false;
905   }
906 
907   if (ctx->write(ctx, &type, sizeof(int8_t)))
908     return true;
909 
910   ctx->error = EXT_TYPE_WRITING_ERROR;
911   return false;
912 }
913 
cmp_write_ext32(cmp_ctx_t * ctx,int8_t tp,uint32_t sz,const void * data)914 bool cmp_write_ext32(cmp_ctx_t *ctx, int8_t tp, uint32_t sz, const void *data) {
915   if (!cmp_write_ext32_marker(ctx, tp, sz))
916     return false;
917 
918   if (ctx->write(ctx, data, sz))
919     return true;
920 
921   ctx->error = DATA_WRITING_ERROR;
922   return false;
923 }
924 
cmp_write_ext_marker(cmp_ctx_t * ctx,int8_t tp,uint32_t sz)925 bool cmp_write_ext_marker(cmp_ctx_t *ctx, int8_t tp, uint32_t sz) {
926   if (sz == 1)
927     return cmp_write_fixext1_marker(ctx, tp);
928   if (sz == 2)
929     return cmp_write_fixext2_marker(ctx, tp);
930   if (sz == 4)
931     return cmp_write_fixext4_marker(ctx, tp);
932   if (sz == 8)
933     return cmp_write_fixext8_marker(ctx, tp);
934   if (sz == 16)
935     return cmp_write_fixext16_marker(ctx, tp);
936   if (sz <= 0xFF)
937     return cmp_write_ext8_marker(ctx, tp, sz);
938   if (sz <= 0xFFFF)
939     return cmp_write_ext16_marker(ctx, tp, sz);
940 
941   return cmp_write_ext32_marker(ctx, tp, sz);
942 }
943 
cmp_write_ext(cmp_ctx_t * ctx,int8_t tp,uint32_t sz,const void * data)944 bool cmp_write_ext(cmp_ctx_t *ctx, int8_t tp, uint32_t sz, const void *data) {
945   if (sz == 1)
946     return cmp_write_fixext1(ctx, tp, data);
947   if (sz == 2)
948     return cmp_write_fixext2(ctx, tp, data);
949   if (sz == 4)
950     return cmp_write_fixext4(ctx, tp, data);
951   if (sz == 8)
952     return cmp_write_fixext8(ctx, tp, data);
953   if (sz == 16)
954     return cmp_write_fixext16(ctx, tp, data);
955   if (sz <= 0xFF)
956     return cmp_write_ext8(ctx, tp, sz, data);
957   if (sz <= 0xFFFF)
958     return cmp_write_ext16(ctx, tp, sz, data);
959 
960   return cmp_write_ext32(ctx, tp, sz, data);
961 }
962 
cmp_write_object(cmp_ctx_t * ctx,cmp_object_t * obj)963 bool cmp_write_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
964   switch(obj->type) {
965     case CMP_TYPE_POSITIVE_FIXNUM:
966       return cmp_write_pfix(ctx, obj->as.u8);
967     case CMP_TYPE_FIXMAP:
968       return cmp_write_fixmap(ctx, obj->as.map_size);
969     case CMP_TYPE_FIXARRAY:
970       return cmp_write_fixarray(ctx, obj->as.array_size);
971     case CMP_TYPE_FIXSTR:
972       return cmp_write_fixstr_marker(ctx, obj->as.str_size);
973     case CMP_TYPE_NIL:
974       return cmp_write_nil(ctx);
975     case CMP_TYPE_BOOLEAN:
976       if (obj->as.boolean)
977         return cmp_write_true(ctx);
978       return cmp_write_false(ctx);
979     case CMP_TYPE_BIN8:
980       return cmp_write_bin8_marker(ctx, obj->as.bin_size);
981     case CMP_TYPE_BIN16:
982       return cmp_write_bin16_marker(ctx, obj->as.bin_size);
983     case CMP_TYPE_BIN32:
984       return cmp_write_bin32_marker(ctx, obj->as.bin_size);
985     case CMP_TYPE_EXT8:
986       return cmp_write_ext8_marker(ctx, obj->as.ext.type, obj->as.ext.size);
987     case CMP_TYPE_EXT16:
988       return cmp_write_ext16_marker(ctx, obj->as.ext.type, obj->as.ext.size);
989     case CMP_TYPE_EXT32:
990       return cmp_write_ext32_marker(ctx, obj->as.ext.type, obj->as.ext.size);
991     case CMP_TYPE_FLOAT:
992       return cmp_write_float(ctx, obj->as.flt);
993     case CMP_TYPE_DOUBLE:
994       return cmp_write_double(ctx, obj->as.dbl);
995     case CMP_TYPE_UINT8:
996       return cmp_write_u8(ctx, obj->as.u8);
997     case CMP_TYPE_UINT16:
998       return cmp_write_u16(ctx, obj->as.u16);
999     case CMP_TYPE_UINT32:
1000       return cmp_write_u32(ctx, obj->as.u32);
1001     case CMP_TYPE_UINT64:
1002       return cmp_write_u64(ctx, obj->as.u64);
1003     case CMP_TYPE_SINT8:
1004       return cmp_write_s8(ctx, obj->as.s8);
1005     case CMP_TYPE_SINT16:
1006       return cmp_write_s16(ctx, obj->as.s16);
1007     case CMP_TYPE_SINT32:
1008       return cmp_write_s32(ctx, obj->as.s32);
1009     case CMP_TYPE_SINT64:
1010       return cmp_write_s64(ctx, obj->as.s64);
1011     case CMP_TYPE_FIXEXT1:
1012       return cmp_write_fixext1_marker(ctx, obj->as.ext.type);
1013     case CMP_TYPE_FIXEXT2:
1014       return cmp_write_fixext2_marker(ctx, obj->as.ext.type);
1015     case CMP_TYPE_FIXEXT4:
1016       return cmp_write_fixext4_marker(ctx, obj->as.ext.type);
1017     case CMP_TYPE_FIXEXT8:
1018       return cmp_write_fixext8_marker(ctx, obj->as.ext.type);
1019     case CMP_TYPE_FIXEXT16:
1020       return cmp_write_fixext16_marker(ctx, obj->as.ext.type);
1021     case CMP_TYPE_STR8:
1022       return cmp_write_str8_marker(ctx, obj->as.str_size);
1023     case CMP_TYPE_STR16:
1024       return cmp_write_str16_marker(ctx, obj->as.str_size);
1025     case CMP_TYPE_STR32:
1026       return cmp_write_str32_marker(ctx, obj->as.str_size);
1027     case CMP_TYPE_ARRAY16:
1028       return cmp_write_array16(ctx, obj->as.array_size);
1029     case CMP_TYPE_ARRAY32:
1030       return cmp_write_array32(ctx, obj->as.array_size);
1031     case CMP_TYPE_MAP16:
1032       return cmp_write_map16(ctx, obj->as.map_size);
1033     case CMP_TYPE_MAP32:
1034       return cmp_write_map32(ctx, obj->as.map_size);
1035     case CMP_TYPE_NEGATIVE_FIXNUM:
1036       return cmp_write_nfix(ctx, obj->as.s8);
1037     default:
1038       ctx->error = INVALID_TYPE_ERROR;
1039       return false;
1040   }
1041 }
1042 
cmp_read_pfix(cmp_ctx_t * ctx,uint8_t * c)1043 bool cmp_read_pfix(cmp_ctx_t *ctx, uint8_t *c) {
1044   cmp_object_t obj;
1045 
1046   if (!cmp_read_object(ctx, &obj))
1047     return false;
1048 
1049   if (obj.type != CMP_TYPE_POSITIVE_FIXNUM) {
1050     ctx->error = INVALID_TYPE_ERROR;
1051     return false;
1052   }
1053 
1054   *c = obj.as.u8;
1055   return true;
1056 }
1057 
cmp_read_nfix(cmp_ctx_t * ctx,int8_t * c)1058 bool cmp_read_nfix(cmp_ctx_t *ctx, int8_t *c) {
1059   cmp_object_t obj;
1060 
1061   if (!cmp_read_object(ctx, &obj))
1062     return false;
1063 
1064   if (obj.type != CMP_TYPE_NEGATIVE_FIXNUM) {
1065     ctx->error = INVALID_TYPE_ERROR;
1066     return false;
1067   }
1068 
1069   *c = obj.as.s8;
1070   return true;
1071 }
1072 
cmp_read_sfix(cmp_ctx_t * ctx,int8_t * c)1073 bool cmp_read_sfix(cmp_ctx_t *ctx, int8_t *c) {
1074   cmp_object_t obj;
1075 
1076   if (!cmp_read_object(ctx, &obj))
1077     return false;
1078 
1079   switch (obj.type) {
1080     case CMP_TYPE_POSITIVE_FIXNUM:
1081     case CMP_TYPE_NEGATIVE_FIXNUM:
1082       *c = obj.as.s8;
1083       return true;
1084     default:
1085       ctx->error = INVALID_TYPE_ERROR;
1086       return false;
1087   }
1088 }
1089 
cmp_read_s8(cmp_ctx_t * ctx,int8_t * c)1090 bool cmp_read_s8(cmp_ctx_t *ctx, int8_t *c) {
1091   cmp_object_t obj;
1092 
1093   if (!cmp_read_object(ctx, &obj))
1094     return false;
1095 
1096   if (obj.type != CMP_TYPE_SINT8) {
1097     ctx->error = INVALID_TYPE_ERROR;
1098     return false;
1099   }
1100 
1101   *c = obj.as.s8;
1102   return true;
1103 }
1104 
cmp_read_s16(cmp_ctx_t * ctx,int16_t * s)1105 bool cmp_read_s16(cmp_ctx_t *ctx, int16_t *s) {
1106   cmp_object_t obj;
1107 
1108   if (!cmp_read_object(ctx, &obj))
1109     return false;
1110 
1111   if (obj.type != CMP_TYPE_SINT16) {
1112     ctx->error = INVALID_TYPE_ERROR;
1113     return false;
1114   }
1115 
1116   *s = obj.as.s16;
1117   return true;
1118 }
1119 
cmp_read_s32(cmp_ctx_t * ctx,int32_t * i)1120 bool cmp_read_s32(cmp_ctx_t *ctx, int32_t *i) {
1121   cmp_object_t obj;
1122 
1123   if (!cmp_read_object(ctx, &obj))
1124     return false;
1125 
1126   if (obj.type != CMP_TYPE_SINT32) {
1127     ctx->error = INVALID_TYPE_ERROR;
1128     return false;
1129   }
1130 
1131   *i = obj.as.s32;
1132   return true;
1133 }
1134 
cmp_read_s64(cmp_ctx_t * ctx,int64_t * l)1135 bool cmp_read_s64(cmp_ctx_t *ctx, int64_t *l) {
1136   cmp_object_t obj;
1137 
1138   if (!cmp_read_object(ctx, &obj))
1139     return false;
1140 
1141   if (obj.type != CMP_TYPE_SINT64) {
1142     ctx->error = INVALID_TYPE_ERROR;
1143     return false;
1144   }
1145 
1146   *l = obj.as.s64;
1147   return true;
1148 }
1149 
cmp_read_char(cmp_ctx_t * ctx,int8_t * c)1150 bool cmp_read_char(cmp_ctx_t *ctx, int8_t *c) {
1151   cmp_object_t obj;
1152 
1153   if (!cmp_read_object(ctx, &obj))
1154     return false;
1155 
1156   switch (obj.type) {
1157     case CMP_TYPE_POSITIVE_FIXNUM:
1158     case CMP_TYPE_NEGATIVE_FIXNUM:
1159     case CMP_TYPE_SINT8:
1160       *c = obj.as.s8;
1161       return true;
1162     case CMP_TYPE_UINT8:
1163       if (obj.as.u8 <= 127) {
1164         *c = obj.as.u8;
1165         return true;
1166       }
1167     default:
1168       ctx->error = INVALID_TYPE_ERROR;
1169       return false;
1170   }
1171 }
1172 
cmp_read_short(cmp_ctx_t * ctx,int16_t * s)1173 bool cmp_read_short(cmp_ctx_t *ctx, int16_t *s) {
1174   cmp_object_t obj;
1175 
1176   if (!cmp_read_object(ctx, &obj))
1177     return false;
1178 
1179   switch (obj.type) {
1180     case CMP_TYPE_POSITIVE_FIXNUM:
1181     case CMP_TYPE_NEGATIVE_FIXNUM:
1182     case CMP_TYPE_SINT8:
1183       *s = obj.as.s8;
1184       return true;
1185     case CMP_TYPE_UINT8:
1186       *s = obj.as.u8;
1187       return true;
1188     case CMP_TYPE_SINT16:
1189       *s = obj.as.s16;
1190       return true;
1191     case CMP_TYPE_UINT16:
1192       if (obj.as.u16 <= 32767) {
1193         *s = obj.as.u16;
1194         return true;
1195       }
1196     default:
1197       ctx->error = INVALID_TYPE_ERROR;
1198       return false;
1199   }
1200 }
1201 
cmp_read_int(cmp_ctx_t * ctx,int32_t * i)1202 bool cmp_read_int(cmp_ctx_t *ctx, int32_t *i) {
1203   cmp_object_t obj;
1204 
1205   if (!cmp_read_object(ctx, &obj))
1206     return false;
1207 
1208   switch (obj.type) {
1209     case CMP_TYPE_POSITIVE_FIXNUM:
1210     case CMP_TYPE_NEGATIVE_FIXNUM:
1211     case CMP_TYPE_SINT8:
1212       *i = obj.as.s8;
1213       return true;
1214     case CMP_TYPE_UINT8:
1215       *i = obj.as.u8;
1216       return true;
1217     case CMP_TYPE_SINT16:
1218       *i = obj.as.s16;
1219       return true;
1220     case CMP_TYPE_UINT16:
1221       *i = obj.as.u16;
1222       return true;
1223     case CMP_TYPE_SINT32:
1224       *i = obj.as.s32;
1225       return true;
1226     case CMP_TYPE_UINT32:
1227       if (obj.as.u32 <= 2147483647) {
1228         *i = obj.as.u32;
1229         return true;
1230       }
1231     default:
1232       ctx->error = INVALID_TYPE_ERROR;
1233       return false;
1234   }
1235 }
1236 
cmp_read_long(cmp_ctx_t * ctx,int64_t * d)1237 bool cmp_read_long(cmp_ctx_t *ctx, int64_t *d) {
1238   cmp_object_t obj;
1239 
1240   if (!cmp_read_object(ctx, &obj))
1241     return false;
1242 
1243   switch (obj.type) {
1244     case CMP_TYPE_POSITIVE_FIXNUM:
1245     case CMP_TYPE_NEGATIVE_FIXNUM:
1246     case CMP_TYPE_SINT8:
1247       *d = obj.as.s8;
1248       return true;
1249     case CMP_TYPE_UINT8:
1250       *d = obj.as.u8;
1251       return true;
1252     case CMP_TYPE_SINT16:
1253       *d = obj.as.s16;
1254       return true;
1255     case CMP_TYPE_UINT16:
1256       *d = obj.as.u16;
1257       return true;
1258     case CMP_TYPE_SINT32:
1259       *d = obj.as.s32;
1260       return true;
1261     case CMP_TYPE_UINT32:
1262       *d = obj.as.u32;
1263       return true;
1264     case CMP_TYPE_SINT64:
1265       *d = obj.as.s64;
1266       return true;
1267     case CMP_TYPE_UINT64:
1268       if (obj.as.u64 <= 9223372036854775807) {
1269         *d = obj.as.u64;
1270         return true;
1271       }
1272     default:
1273       ctx->error = INVALID_TYPE_ERROR;
1274       return false;
1275   }
1276 }
1277 
cmp_read_sinteger(cmp_ctx_t * ctx,int64_t * d)1278 bool cmp_read_sinteger(cmp_ctx_t *ctx, int64_t *d) {
1279   return cmp_read_long(ctx, d);
1280 }
1281 
cmp_read_ufix(cmp_ctx_t * ctx,uint8_t * c)1282 bool cmp_read_ufix(cmp_ctx_t *ctx, uint8_t *c) {
1283   cmp_object_t obj;
1284 
1285   if (!cmp_read_object(ctx, &obj))
1286     return false;
1287 
1288   if (obj.type != CMP_TYPE_NEGATIVE_FIXNUM) {
1289     ctx->error = INVALID_TYPE_ERROR;
1290     return false;
1291   }
1292 
1293   *c = obj.as.u8;
1294   return true;
1295 }
1296 
cmp_read_u8(cmp_ctx_t * ctx,uint8_t * c)1297 bool cmp_read_u8(cmp_ctx_t *ctx, uint8_t *c) {
1298   cmp_object_t obj;
1299 
1300   if (!cmp_read_object(ctx, &obj))
1301     return false;
1302 
1303   if (obj.type != CMP_TYPE_UINT8) {
1304     ctx->error = INVALID_TYPE_ERROR;
1305     return false;
1306   }
1307 
1308   *c = obj.as.u8;
1309   return true;
1310 }
1311 
cmp_read_u16(cmp_ctx_t * ctx,uint16_t * s)1312 bool cmp_read_u16(cmp_ctx_t *ctx, uint16_t *s) {
1313   cmp_object_t obj;
1314 
1315   if (!cmp_read_object(ctx, &obj))
1316     return false;
1317 
1318   if (obj.type != CMP_TYPE_UINT16) {
1319     ctx->error = INVALID_TYPE_ERROR;
1320     return false;
1321   }
1322 
1323   *s = obj.as.u16;
1324   return true;
1325 }
1326 
cmp_read_u32(cmp_ctx_t * ctx,uint32_t * i)1327 bool cmp_read_u32(cmp_ctx_t *ctx, uint32_t *i) {
1328   cmp_object_t obj;
1329 
1330   if (!cmp_read_object(ctx, &obj))
1331     return false;
1332 
1333   if (obj.type != CMP_TYPE_UINT32) {
1334     ctx->error = INVALID_TYPE_ERROR;
1335     return false;
1336   }
1337 
1338   *i = obj.as.u32;
1339   return true;
1340 }
1341 
cmp_read_u64(cmp_ctx_t * ctx,uint64_t * l)1342 bool cmp_read_u64(cmp_ctx_t *ctx, uint64_t *l) {
1343   cmp_object_t obj;
1344 
1345   if (!cmp_read_object(ctx, &obj))
1346     return false;
1347 
1348   if (obj.type != CMP_TYPE_UINT64) {
1349     ctx->error = INVALID_TYPE_ERROR;
1350     return false;
1351   }
1352 
1353   *l = obj.as.u64;
1354   return true;
1355 }
1356 
cmp_read_uchar(cmp_ctx_t * ctx,uint8_t * c)1357 bool cmp_read_uchar(cmp_ctx_t *ctx, uint8_t *c) {
1358   cmp_object_t obj;
1359 
1360   if (!cmp_read_object(ctx, &obj))
1361     return false;
1362 
1363   switch (obj.type) {
1364     case CMP_TYPE_POSITIVE_FIXNUM:
1365     case CMP_TYPE_UINT8:
1366       *c = obj.as.u8;
1367       return true;
1368     default:
1369       ctx->error = INVALID_TYPE_ERROR;
1370       return false;
1371   }
1372 }
1373 
cmp_read_ushort(cmp_ctx_t * ctx,uint16_t * s)1374 bool cmp_read_ushort(cmp_ctx_t *ctx, uint16_t *s) {
1375   cmp_object_t obj;
1376 
1377   if (!cmp_read_object(ctx, &obj))
1378     return false;
1379 
1380   switch (obj.type) {
1381     case CMP_TYPE_POSITIVE_FIXNUM:
1382     case CMP_TYPE_UINT8:
1383       *s = obj.as.u8;
1384       return true;
1385     case CMP_TYPE_UINT16:
1386       *s = obj.as.u16;
1387       return true;
1388     default:
1389       ctx->error = INVALID_TYPE_ERROR;
1390       return false;
1391   }
1392 }
1393 
cmp_read_uint(cmp_ctx_t * ctx,uint32_t * i)1394 bool cmp_read_uint(cmp_ctx_t *ctx, uint32_t *i) {
1395   cmp_object_t obj;
1396 
1397   if (!cmp_read_object(ctx, &obj))
1398     return false;
1399 
1400   switch (obj.type) {
1401     case CMP_TYPE_POSITIVE_FIXNUM:
1402     case CMP_TYPE_UINT8:
1403       *i = obj.as.u8;
1404       return true;
1405     case CMP_TYPE_UINT16:
1406       *i = obj.as.u16;
1407       return true;
1408     case CMP_TYPE_UINT32:
1409       *i = obj.as.u32;
1410       return true;
1411     default:
1412       ctx->error = INVALID_TYPE_ERROR;
1413       return false;
1414   }
1415 }
1416 
cmp_read_ulong(cmp_ctx_t * ctx,uint64_t * u)1417 bool cmp_read_ulong(cmp_ctx_t *ctx, uint64_t *u) {
1418   cmp_object_t obj;
1419 
1420   if (!cmp_read_object(ctx, &obj))
1421     return false;
1422 
1423   switch (obj.type) {
1424     case CMP_TYPE_POSITIVE_FIXNUM:
1425     case CMP_TYPE_UINT8:
1426       *u = obj.as.u8;
1427       return true;
1428     case CMP_TYPE_UINT16:
1429       *u = obj.as.u16;
1430       return true;
1431     case CMP_TYPE_UINT32:
1432       *u = obj.as.u32;
1433       return true;
1434     case CMP_TYPE_UINT64:
1435       *u = obj.as.u64;
1436       return true;
1437     default:
1438       ctx->error = INVALID_TYPE_ERROR;
1439       return false;
1440   }
1441 }
1442 
cmp_read_uinteger(cmp_ctx_t * ctx,uint64_t * d)1443 bool cmp_read_uinteger(cmp_ctx_t *ctx, uint64_t *d) {
1444   return cmp_read_ulong(ctx, d);
1445 }
1446 
cmp_read_float(cmp_ctx_t * ctx,float * f)1447 bool cmp_read_float(cmp_ctx_t *ctx, float *f) {
1448   cmp_object_t obj;
1449 
1450   if (!cmp_read_object(ctx, &obj))
1451     return false;
1452 
1453   if (obj.type != CMP_TYPE_FLOAT) {
1454     ctx->error = INVALID_TYPE_ERROR;
1455     return false;
1456   }
1457 
1458   *f = obj.as.flt;
1459 
1460   return true;
1461 }
1462 
cmp_read_double(cmp_ctx_t * ctx,double * d)1463 bool cmp_read_double(cmp_ctx_t *ctx, double *d) {
1464   cmp_object_t obj;
1465 
1466   if (!cmp_read_object(ctx, &obj))
1467     return false;
1468 
1469   if (obj.type != CMP_TYPE_DOUBLE) {
1470     ctx->error = INVALID_TYPE_ERROR;
1471     return false;
1472   }
1473 
1474   *d = obj.as.dbl;
1475 
1476   return true;
1477 }
1478 
cmp_read_nil(cmp_ctx_t * ctx)1479 bool cmp_read_nil(cmp_ctx_t *ctx) {
1480   cmp_object_t obj;
1481 
1482   if (!cmp_read_object(ctx, &obj))
1483     return false;
1484 
1485   if (obj.type == CMP_TYPE_NIL)
1486     return true;
1487 
1488   ctx->error = INVALID_TYPE_ERROR;
1489   return false;
1490 }
1491 
cmp_read_bool(cmp_ctx_t * ctx,bool * b)1492 bool cmp_read_bool(cmp_ctx_t *ctx, bool *b) {
1493   cmp_object_t obj;
1494 
1495   if (!cmp_read_object(ctx, &obj))
1496     return false;
1497 
1498   if (obj.type != CMP_TYPE_BOOLEAN) {
1499     ctx->error = INVALID_TYPE_ERROR;
1500     return false;
1501   }
1502 
1503   if (obj.as.boolean)
1504     *b = true;
1505   else
1506     *b = false;
1507 
1508   return true;
1509 }
1510 
cmp_read_bool_as_u8(cmp_ctx_t * ctx,uint8_t * b)1511 bool cmp_read_bool_as_u8(cmp_ctx_t *ctx, uint8_t *b) {
1512   cmp_object_t obj;
1513 
1514   if (!cmp_read_object(ctx, &obj))
1515     return false;
1516 
1517   if (obj.type != CMP_TYPE_BOOLEAN) {
1518     ctx->error = INVALID_TYPE_ERROR;
1519     return false;
1520   }
1521 
1522   if (obj.as.boolean)
1523     *b = 1;
1524   else
1525     *b = 0;
1526 
1527   return true;
1528 }
1529 
cmp_read_str_size(cmp_ctx_t * ctx,uint32_t * size)1530 bool cmp_read_str_size(cmp_ctx_t *ctx, uint32_t *size) {
1531   cmp_object_t obj;
1532 
1533   if (!cmp_read_object(ctx, &obj))
1534     return false;
1535 
1536   switch (obj.type) {
1537     case CMP_TYPE_FIXSTR:
1538     case CMP_TYPE_STR8:
1539     case CMP_TYPE_STR16:
1540     case CMP_TYPE_STR32:
1541       *size = obj.as.str_size;
1542       return true;
1543     default:
1544       ctx->error = INVALID_TYPE_ERROR;
1545       return false;
1546   }
1547 }
1548 
cmp_read_str(cmp_ctx_t * ctx,char * data,uint32_t * size)1549 bool cmp_read_str(cmp_ctx_t *ctx, char *data, uint32_t *size) {
1550   uint32_t str_size = 0;
1551 
1552   if (!cmp_read_str_size(ctx, &str_size))
1553     return false;
1554 
1555   if ((str_size + 1) > *size) {
1556     *size = str_size;
1557     ctx->error = STR_DATA_LENGTH_TOO_LONG_ERROR;
1558     return false;
1559   }
1560 
1561   if (!ctx->read(ctx, data, str_size)) {
1562     ctx->error = DATA_READING_ERROR;
1563     return false;
1564   }
1565 
1566   data[str_size] = 0;
1567 
1568   *size = str_size;
1569   return true;
1570 }
1571 
cmp_read_bin_size(cmp_ctx_t * ctx,uint32_t * size)1572 bool cmp_read_bin_size(cmp_ctx_t *ctx, uint32_t *size) {
1573   cmp_object_t obj;
1574 
1575   if (!cmp_read_object(ctx, &obj))
1576     return false;
1577 
1578   switch (obj.type) {
1579     case CMP_TYPE_BIN8:
1580     case CMP_TYPE_BIN16:
1581     case CMP_TYPE_BIN32:
1582       *size = obj.as.bin_size;
1583       return true;
1584     default:
1585       ctx->error = INVALID_TYPE_ERROR;
1586       return false;
1587   }
1588 }
1589 
cmp_read_bin(cmp_ctx_t * ctx,void * data,uint32_t * size)1590 bool cmp_read_bin(cmp_ctx_t *ctx, void *data, uint32_t *size) {
1591   uint32_t bin_size = 0;
1592 
1593   if (!cmp_read_bin_size(ctx, &bin_size))
1594     return false;
1595 
1596   if (bin_size > *size) {
1597     ctx->error = BIN_DATA_LENGTH_TOO_LONG_ERROR;
1598     return false;
1599   }
1600 
1601   if (!ctx->read(ctx, data, bin_size)) {
1602     ctx->error = DATA_READING_ERROR;
1603     return false;
1604   }
1605 
1606   *size = bin_size;
1607   return true;
1608 }
1609 
cmp_read_array(cmp_ctx_t * ctx,uint32_t * size)1610 bool cmp_read_array(cmp_ctx_t *ctx, uint32_t *size) {
1611   cmp_object_t obj;
1612 
1613   if (!cmp_read_object(ctx, &obj))
1614     return false;
1615 
1616   switch (obj.type) {
1617     case CMP_TYPE_FIXARRAY:
1618     case CMP_TYPE_ARRAY16:
1619     case CMP_TYPE_ARRAY32:
1620       *size = obj.as.array_size;
1621       return true;
1622     default:
1623       ctx->error = INVALID_TYPE_ERROR;
1624       return false;
1625   }
1626 }
1627 
cmp_read_map(cmp_ctx_t * ctx,uint32_t * size)1628 bool cmp_read_map(cmp_ctx_t *ctx, uint32_t *size) {
1629   cmp_object_t obj;
1630 
1631   if (!cmp_read_object(ctx, &obj))
1632     return false;
1633 
1634   switch (obj.type) {
1635     case CMP_TYPE_FIXMAP:
1636     case CMP_TYPE_MAP16:
1637     case CMP_TYPE_MAP32:
1638       *size = obj.as.map_size;
1639       return true;
1640     default:
1641       ctx->error = INVALID_TYPE_ERROR;
1642       return false;
1643   }
1644 }
1645 
cmp_read_fixext1_marker(cmp_ctx_t * ctx,int8_t * type)1646 bool cmp_read_fixext1_marker(cmp_ctx_t *ctx, int8_t *type) {
1647   cmp_object_t obj;
1648 
1649   if (!cmp_read_object(ctx, &obj))
1650     return false;
1651 
1652   if (obj.type != CMP_TYPE_FIXEXT1) {
1653     ctx->error = INVALID_TYPE_ERROR;
1654     return false;
1655   }
1656 
1657   *type = obj.as.ext.type;
1658   return true;
1659 }
1660 
cmp_read_fixext1(cmp_ctx_t * ctx,int8_t * type,void * data)1661 bool cmp_read_fixext1(cmp_ctx_t *ctx, int8_t *type, void *data) {
1662   if (!cmp_read_fixext1_marker(ctx, type))
1663     return false;
1664 
1665   if (ctx->read(ctx, data, 1))
1666     return true;
1667 
1668   ctx->error = DATA_READING_ERROR;
1669   return false;
1670 }
1671 
cmp_read_fixext2_marker(cmp_ctx_t * ctx,int8_t * type)1672 bool cmp_read_fixext2_marker(cmp_ctx_t *ctx, int8_t *type) {
1673   cmp_object_t obj;
1674 
1675   if (!cmp_read_object(ctx, &obj))
1676     return false;
1677 
1678   if (obj.type != CMP_TYPE_FIXEXT2) {
1679     ctx->error = INVALID_TYPE_ERROR;
1680     return false;
1681   }
1682 
1683   *type = obj.as.ext.type;
1684   return true;
1685 }
1686 
cmp_read_fixext2(cmp_ctx_t * ctx,int8_t * type,void * data)1687 bool cmp_read_fixext2(cmp_ctx_t *ctx, int8_t *type, void *data) {
1688   if (!cmp_read_fixext2_marker(ctx, type))
1689     return false;
1690 
1691   if (ctx->read(ctx, data, 2))
1692     return true;
1693 
1694   ctx->error = DATA_READING_ERROR;
1695   return false;
1696 }
1697 
cmp_read_fixext4_marker(cmp_ctx_t * ctx,int8_t * type)1698 bool cmp_read_fixext4_marker(cmp_ctx_t *ctx, int8_t *type) {
1699   cmp_object_t obj;
1700 
1701   if (!cmp_read_object(ctx, &obj))
1702     return false;
1703 
1704   if (obj.type != CMP_TYPE_FIXEXT4) {
1705     ctx->error = INVALID_TYPE_ERROR;
1706     return false;
1707   }
1708 
1709   *type = obj.as.ext.type;
1710   return true;
1711 }
1712 
cmp_read_fixext4(cmp_ctx_t * ctx,int8_t * type,void * data)1713 bool cmp_read_fixext4(cmp_ctx_t *ctx, int8_t *type, void *data) {
1714   if (!cmp_read_fixext4_marker(ctx, type))
1715     return false;
1716 
1717   if (ctx->read(ctx, data, 4))
1718     return true;
1719 
1720   ctx->error = DATA_READING_ERROR;
1721   return false;
1722 }
1723 
cmp_read_fixext8_marker(cmp_ctx_t * ctx,int8_t * type)1724 bool cmp_read_fixext8_marker(cmp_ctx_t *ctx, int8_t *type) {
1725   cmp_object_t obj;
1726 
1727   if (!cmp_read_object(ctx, &obj))
1728     return false;
1729 
1730   if (obj.type != CMP_TYPE_FIXEXT8) {
1731     ctx->error = INVALID_TYPE_ERROR;
1732     return false;
1733   }
1734 
1735   *type = obj.as.ext.type;
1736   return true;
1737 }
1738 
cmp_read_fixext8(cmp_ctx_t * ctx,int8_t * type,void * data)1739 bool cmp_read_fixext8(cmp_ctx_t *ctx, int8_t *type, void *data) {
1740   if (!cmp_read_fixext8_marker(ctx, type))
1741     return false;
1742 
1743   if (ctx->read(ctx, data, 8))
1744     return true;
1745 
1746   ctx->error = DATA_READING_ERROR;
1747   return false;
1748 }
1749 
cmp_read_fixext16_marker(cmp_ctx_t * ctx,int8_t * type)1750 bool cmp_read_fixext16_marker(cmp_ctx_t *ctx, int8_t *type) {
1751   cmp_object_t obj;
1752 
1753   if (!cmp_read_object(ctx, &obj))
1754     return false;
1755 
1756   if (obj.type != CMP_TYPE_FIXEXT16) {
1757     ctx->error = INVALID_TYPE_ERROR;
1758     return false;
1759   }
1760 
1761   *type = obj.as.ext.type;
1762   return true;
1763 }
1764 
cmp_read_fixext16(cmp_ctx_t * ctx,int8_t * type,void * data)1765 bool cmp_read_fixext16(cmp_ctx_t *ctx, int8_t *type, void *data) {
1766   if (!cmp_read_fixext16_marker(ctx, type))
1767     return false;
1768 
1769   if (ctx->read(ctx, data, 16))
1770     return true;
1771 
1772   ctx->error = DATA_READING_ERROR;
1773   return false;
1774 }
1775 
cmp_read_ext8_marker(cmp_ctx_t * ctx,int8_t * type,uint8_t * size)1776 bool cmp_read_ext8_marker(cmp_ctx_t *ctx, int8_t *type, uint8_t *size) {
1777   cmp_object_t obj;
1778 
1779   if (!cmp_read_object(ctx, &obj))
1780     return false;
1781 
1782   if (obj.type != CMP_TYPE_EXT8) {
1783     ctx->error = INVALID_TYPE_ERROR;
1784     return false;
1785   }
1786 
1787   *type = obj.as.ext.type;
1788   *size = obj.as.ext.size;
1789 
1790   return true;
1791 }
1792 
cmp_read_ext8(cmp_ctx_t * ctx,int8_t * type,uint8_t * size,void * data)1793 bool cmp_read_ext8(cmp_ctx_t *ctx, int8_t *type, uint8_t *size, void *data) {
1794   if (!cmp_read_ext8_marker(ctx, type, size))
1795     return false;
1796 
1797   if (ctx->read(ctx, data, *size))
1798     return true;
1799 
1800   ctx->error = DATA_READING_ERROR;
1801   return false;
1802 }
1803 
cmp_read_ext16_marker(cmp_ctx_t * ctx,int8_t * type,uint16_t * size)1804 bool cmp_read_ext16_marker(cmp_ctx_t *ctx, int8_t *type, uint16_t *size) {
1805   cmp_object_t obj;
1806 
1807   if (!cmp_read_object(ctx, &obj))
1808     return false;
1809 
1810   if (obj.type != CMP_TYPE_EXT16) {
1811     ctx->error = INVALID_TYPE_ERROR;
1812     return false;
1813   }
1814 
1815   *type = obj.as.ext.type;
1816   *size = obj.as.ext.size;
1817 
1818   return true;
1819 }
1820 
cmp_read_ext16(cmp_ctx_t * ctx,int8_t * type,uint16_t * size,void * data)1821 bool cmp_read_ext16(cmp_ctx_t *ctx, int8_t *type, uint16_t *size, void *data) {
1822   if (!cmp_read_ext16_marker(ctx, type, size))
1823     return false;
1824 
1825   if (ctx->read(ctx, data, *size))
1826     return true;
1827 
1828   ctx->error = DATA_READING_ERROR;
1829   return false;
1830 }
1831 
cmp_read_ext32_marker(cmp_ctx_t * ctx,int8_t * type,uint32_t * size)1832 bool cmp_read_ext32_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size) {
1833   cmp_object_t obj;
1834 
1835   if (!cmp_read_object(ctx, &obj))
1836     return false;
1837 
1838   if (obj.type != CMP_TYPE_EXT32) {
1839     ctx->error = INVALID_TYPE_ERROR;
1840     return false;
1841   }
1842 
1843   *type = obj.as.ext.type;
1844   *size = obj.as.ext.size;
1845 
1846   return true;
1847 }
1848 
cmp_read_ext32(cmp_ctx_t * ctx,int8_t * type,uint32_t * size,void * data)1849 bool cmp_read_ext32(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data) {
1850   if (!cmp_read_ext32_marker(ctx, type, size))
1851     return false;
1852 
1853   if (ctx->read(ctx, data, *size))
1854     return true;
1855 
1856   ctx->error = DATA_READING_ERROR;
1857   return false;
1858 }
1859 
cmp_read_ext_marker(cmp_ctx_t * ctx,int8_t * type,uint32_t * size)1860 bool cmp_read_ext_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size) {
1861   cmp_object_t obj;
1862 
1863   if (!cmp_read_object(ctx, &obj))
1864     return false;
1865 
1866   switch (obj.type) {
1867     case CMP_TYPE_FIXEXT1:
1868     case CMP_TYPE_FIXEXT2:
1869     case CMP_TYPE_FIXEXT4:
1870     case CMP_TYPE_FIXEXT8:
1871     case CMP_TYPE_FIXEXT16:
1872     case CMP_TYPE_EXT8:
1873     case CMP_TYPE_EXT16:
1874     case CMP_TYPE_EXT32:
1875       *type = obj.as.ext.type;
1876       *size = obj.as.ext.size;
1877       return true;
1878     default:
1879       ctx->error = INVALID_TYPE_ERROR;
1880       return false;
1881   }
1882 }
1883 
cmp_read_ext(cmp_ctx_t * ctx,int8_t * type,uint32_t * size,void * data)1884 bool cmp_read_ext(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data) {
1885   if (!cmp_read_ext_marker(ctx, type, size))
1886     return false;
1887 
1888   if (ctx->read(ctx, data, *size))
1889     return true;
1890 
1891   ctx->error = DATA_READING_ERROR;
1892   return false;
1893 }
1894 
cmp_read_object(cmp_ctx_t * ctx,cmp_object_t * obj)1895 bool cmp_read_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
1896   uint8_t type_marker = 0;
1897 
1898   if (!read_type_marker(ctx, &type_marker))
1899     return false;
1900 
1901   if (type_marker <= 0x7F) {
1902     obj->type = CMP_TYPE_POSITIVE_FIXNUM;
1903     obj->as.u8 = type_marker;
1904   }
1905   else if (type_marker <= 0x8F) {
1906     obj->type = CMP_TYPE_FIXMAP;
1907     obj->as.map_size = type_marker & FIXMAP_SIZE;
1908   }
1909   else if (type_marker <= 0x9F) {
1910     obj->type = CMP_TYPE_FIXARRAY;
1911     obj->as.array_size = type_marker & FIXARRAY_SIZE;
1912   }
1913   else if (type_marker <= 0xBF) {
1914     obj->type = CMP_TYPE_FIXSTR;
1915     obj->as.str_size = type_marker & FIXSTR_SIZE;
1916   }
1917   else if (type_marker == NIL_MARKER) {
1918     obj->type = CMP_TYPE_NIL;
1919     obj->as.u8 = 0;
1920   }
1921   else if (type_marker == FALSE_MARKER) {
1922     obj->type = CMP_TYPE_BOOLEAN;
1923     obj->as.boolean = false;
1924   }
1925   else if (type_marker == TRUE_MARKER) {
1926     obj->type = CMP_TYPE_BOOLEAN;
1927     obj->as.boolean = true;
1928   }
1929   else if (type_marker == BIN8_MARKER) {
1930     obj->type = CMP_TYPE_BIN8;
1931     if (!ctx->read(ctx, &obj->as.u8, sizeof(uint8_t))) {
1932       ctx->error = LENGTH_READING_ERROR;
1933       return false;
1934     }
1935     obj->as.bin_size = obj->as.u8;
1936   }
1937   else if (type_marker == BIN16_MARKER) {
1938     obj->type = CMP_TYPE_BIN16;
1939     if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
1940       ctx->error = LENGTH_READING_ERROR;
1941       return false;
1942     }
1943     obj->as.bin_size = be16(obj->as.u16);
1944   }
1945   else if (type_marker == BIN32_MARKER) {
1946     obj->type = CMP_TYPE_BIN32;
1947     if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
1948       ctx->error = LENGTH_READING_ERROR;
1949       return false;
1950     }
1951     obj->as.bin_size = be32(obj->as.u32);
1952   }
1953   else if (type_marker == EXT8_MARKER) {
1954     uint8_t ext_size;
1955     int8_t ext_type;
1956 
1957     obj->type = CMP_TYPE_EXT8;
1958     if (!ctx->read(ctx, &ext_size, sizeof(uint8_t))) {
1959       ctx->error = LENGTH_READING_ERROR;
1960       return false;
1961     }
1962     if (!ctx->read(ctx, &ext_type, sizeof(int8_t))) {
1963       ctx->error = EXT_TYPE_READING_ERROR;
1964       return false;
1965     }
1966     obj->as.ext.size = ext_size;
1967     obj->as.ext.type = ext_type;
1968   }
1969   else if (type_marker == EXT16_MARKER) {
1970     int8_t ext_type;
1971     uint16_t ext_size;
1972 
1973     obj->type = CMP_TYPE_EXT16;
1974     if (!ctx->read(ctx, &ext_size, sizeof(uint16_t))) {
1975       ctx->error = LENGTH_READING_ERROR;
1976       return false;
1977     }
1978     if (!ctx->read(ctx, &ext_type, sizeof(int8_t))) {
1979       ctx->error = EXT_TYPE_READING_ERROR;
1980       return false;
1981     }
1982     obj->as.ext.size = be16(ext_size);
1983     obj->as.ext.type = ext_type;
1984   }
1985   else if (type_marker == EXT32_MARKER) {
1986     int8_t ext_type;
1987     uint32_t ext_size;
1988 
1989     obj->type = CMP_TYPE_EXT32;
1990     if (!ctx->read(ctx, &ext_size, sizeof(uint32_t))) {
1991       ctx->error = LENGTH_READING_ERROR;
1992       return false;
1993     }
1994     if (!ctx->read(ctx, &ext_type, sizeof(int8_t))) {
1995       ctx->error = EXT_TYPE_READING_ERROR;
1996       return false;
1997     }
1998     obj->as.ext.size = be32(ext_size);
1999     obj->as.ext.type = ext_type;
2000   }
2001   else if (type_marker == FLOAT_MARKER) {
2002     obj->type = CMP_TYPE_FLOAT;
2003     if (!ctx->read(ctx, &obj->as.flt, sizeof(float))) {
2004       ctx->error = DATA_READING_ERROR;
2005       return false;
2006     }
2007     obj->as.flt = befloat(obj->as.flt);
2008   }
2009   else if (type_marker == DOUBLE_MARKER) {
2010     obj->type = CMP_TYPE_DOUBLE;
2011     if (!ctx->read(ctx, &obj->as.dbl, sizeof(double))) {
2012       ctx->error = DATA_READING_ERROR;
2013       return false;
2014     }
2015     obj->as.dbl = bedouble(obj->as.dbl);
2016   }
2017   else if (type_marker == U8_MARKER) {
2018     obj->type = CMP_TYPE_UINT8;
2019     if (!ctx->read(ctx, &obj->as.u8, sizeof(uint8_t))) {
2020       ctx->error = DATA_READING_ERROR;
2021       return false;
2022     }
2023   }
2024   else if (type_marker == U16_MARKER) {
2025     obj->type = CMP_TYPE_UINT16;
2026     if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
2027       ctx->error = DATA_READING_ERROR;
2028       return false;
2029     }
2030     obj->as.u16 = be16(obj->as.u16);
2031   }
2032   else if (type_marker == U32_MARKER) {
2033     obj->type = CMP_TYPE_UINT32;
2034     if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
2035       ctx->error = DATA_READING_ERROR;
2036       return false;
2037     }
2038     obj->as.u32 = be32(obj->as.u32);
2039   }
2040   else if (type_marker == U64_MARKER) {
2041     obj->type = CMP_TYPE_UINT64;
2042     if (!ctx->read(ctx, &obj->as.u64, sizeof(uint64_t))) {
2043       ctx->error = DATA_READING_ERROR;
2044       return false;
2045     }
2046     obj->as.u64 = be64(obj->as.u64);
2047   }
2048   else if (type_marker == S8_MARKER) {
2049     obj->type = CMP_TYPE_SINT8;
2050     if (!ctx->read(ctx, &obj->as.s8, sizeof(int8_t))) {
2051       ctx->error = DATA_READING_ERROR;
2052       return false;
2053     }
2054   }
2055   else if (type_marker == S16_MARKER) {
2056     obj->type = CMP_TYPE_SINT16;
2057     if (!ctx->read(ctx, &obj->as.s16, sizeof(int16_t))) {
2058       ctx->error = DATA_READING_ERROR;
2059       return false;
2060     }
2061     obj->as.s16 = be16(obj->as.s16);
2062   }
2063   else if (type_marker == S32_MARKER) {
2064     obj->type = CMP_TYPE_SINT32;
2065     if (!ctx->read(ctx, &obj->as.s32, sizeof(int32_t))) {
2066       ctx->error = DATA_READING_ERROR;
2067       return false;
2068     }
2069     obj->as.s32 = be32(obj->as.s32);
2070   }
2071   else if (type_marker == S64_MARKER) {
2072     obj->type = CMP_TYPE_SINT64;
2073     if (!ctx->read(ctx, &obj->as.s64, sizeof(int64_t))) {
2074       ctx->error = DATA_READING_ERROR;
2075       return false;
2076     }
2077     obj->as.s64 = be64(obj->as.s64);
2078   }
2079   else if (type_marker == FIXEXT1_MARKER) {
2080     obj->type = CMP_TYPE_FIXEXT1;
2081     if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
2082       ctx->error = EXT_TYPE_READING_ERROR;
2083       return false;
2084     }
2085     obj->as.ext.size = 1;
2086   }
2087   else if (type_marker == FIXEXT2_MARKER) {
2088     obj->type = CMP_TYPE_FIXEXT2;
2089     if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
2090       ctx->error = EXT_TYPE_READING_ERROR;
2091       return false;
2092     }
2093     obj->as.ext.size = 2;
2094   }
2095   else if (type_marker == FIXEXT4_MARKER) {
2096     obj->type = CMP_TYPE_FIXEXT4;
2097     if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
2098       ctx->error = EXT_TYPE_READING_ERROR;
2099       return false;
2100     }
2101     obj->as.ext.size = 4;
2102   }
2103   else if (type_marker == FIXEXT8_MARKER) {
2104     obj->type = CMP_TYPE_FIXEXT8;
2105     if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
2106       ctx->error = EXT_TYPE_READING_ERROR;
2107       return false;
2108     }
2109     obj->as.ext.size = 8;
2110   }
2111   else if (type_marker == FIXEXT16_MARKER) {
2112     obj->type = CMP_TYPE_FIXEXT16;
2113     if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
2114       ctx->error = EXT_TYPE_READING_ERROR;
2115       return false;
2116     }
2117     obj->as.ext.size = 16;
2118   }
2119   else if (type_marker == STR8_MARKER) {
2120     obj->type = CMP_TYPE_STR8;
2121     if (!ctx->read(ctx, &obj->as.u8, sizeof(uint8_t))) {
2122       ctx->error = DATA_READING_ERROR;
2123       return false;
2124     }
2125     obj->as.str_size = obj->as.u8;
2126   }
2127   else if (type_marker == STR16_MARKER) {
2128     obj->type = CMP_TYPE_STR16;
2129     if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
2130       ctx->error = DATA_READING_ERROR;
2131       return false;
2132     }
2133     obj->as.str_size = be16(obj->as.u16);
2134   }
2135   else if (type_marker == STR32_MARKER) {
2136     obj->type = CMP_TYPE_STR32;
2137     if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
2138       ctx->error = DATA_READING_ERROR;
2139       return false;
2140     }
2141     obj->as.str_size = be32(obj->as.u32);
2142   }
2143   else if (type_marker == ARRAY16_MARKER) {
2144     obj->type = CMP_TYPE_ARRAY16;
2145     if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
2146       ctx->error = DATA_READING_ERROR;
2147       return false;
2148     }
2149     obj->as.array_size = be16(obj->as.u16);
2150   }
2151   else if (type_marker == ARRAY32_MARKER) {
2152     obj->type = CMP_TYPE_ARRAY32;
2153     if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
2154       ctx->error = DATA_READING_ERROR;
2155       return false;
2156     }
2157     obj->as.array_size = be32(obj->as.u32);
2158   }
2159   else if (type_marker == MAP16_MARKER) {
2160     obj->type = CMP_TYPE_MAP16;
2161     if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
2162       ctx->error = DATA_READING_ERROR;
2163       return false;
2164     }
2165     obj->as.map_size = be16(obj->as.u16);
2166   }
2167   else if (type_marker == MAP32_MARKER) {
2168     obj->type = CMP_TYPE_MAP32;
2169     if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
2170       ctx->error = DATA_READING_ERROR;
2171       return false;
2172     }
2173     obj->as.map_size = be32(obj->as.u32);
2174   }
2175   else if (type_marker >= NEGATIVE_FIXNUM_MARKER) {
2176     obj->type = CMP_TYPE_NEGATIVE_FIXNUM;
2177     obj->as.s8 = type_marker;
2178   }
2179   else {
2180     ctx->error = INVALID_TYPE_ERROR;
2181     return false;
2182   }
2183 
2184   return true;
2185 }
2186 
cmp_object_is_char(cmp_object_t * obj)2187 bool cmp_object_is_char(cmp_object_t *obj) {
2188   switch (obj->type) {
2189     case CMP_TYPE_NEGATIVE_FIXNUM:
2190     case CMP_TYPE_SINT8:
2191       return true;
2192     default:
2193       return false;
2194   }
2195 }
2196 
cmp_object_is_short(cmp_object_t * obj)2197 bool cmp_object_is_short(cmp_object_t *obj) {
2198   switch (obj->type) {
2199     case CMP_TYPE_NEGATIVE_FIXNUM:
2200     case CMP_TYPE_SINT8:
2201     case CMP_TYPE_SINT16:
2202       return true;
2203     default:
2204       return false;
2205   }
2206 }
2207 
cmp_object_is_int(cmp_object_t * obj)2208 bool cmp_object_is_int(cmp_object_t *obj) {
2209   switch (obj->type) {
2210     case CMP_TYPE_NEGATIVE_FIXNUM:
2211     case CMP_TYPE_SINT8:
2212     case CMP_TYPE_SINT16:
2213     case CMP_TYPE_SINT32:
2214       return true;
2215     default:
2216       return false;
2217   }
2218 }
2219 
cmp_object_is_long(cmp_object_t * obj)2220 bool cmp_object_is_long(cmp_object_t *obj) {
2221   switch (obj->type) {
2222     case CMP_TYPE_NEGATIVE_FIXNUM:
2223     case CMP_TYPE_SINT8:
2224     case CMP_TYPE_SINT16:
2225     case CMP_TYPE_SINT32:
2226     case CMP_TYPE_SINT64:
2227       return true;
2228     default:
2229       return false;
2230   }
2231 }
2232 
cmp_object_is_sinteger(cmp_object_t * obj)2233 bool cmp_object_is_sinteger(cmp_object_t *obj) {
2234   return cmp_object_is_long(obj);
2235 }
2236 
cmp_object_is_uchar(cmp_object_t * obj)2237 bool cmp_object_is_uchar(cmp_object_t *obj) {
2238   switch (obj->type) {
2239     case CMP_TYPE_POSITIVE_FIXNUM:
2240     case CMP_TYPE_UINT8:
2241       return true;
2242     default:
2243       return false;
2244   }
2245 }
2246 
cmp_object_is_ushort(cmp_object_t * obj)2247 bool cmp_object_is_ushort(cmp_object_t *obj) {
2248   switch (obj->type) {
2249     case CMP_TYPE_POSITIVE_FIXNUM:
2250     case CMP_TYPE_UINT8:
2251       return true;
2252     case CMP_TYPE_UINT16:
2253       return true;
2254     default:
2255       return false;
2256   }
2257 }
2258 
cmp_object_is_uint(cmp_object_t * obj)2259 bool cmp_object_is_uint(cmp_object_t *obj) {
2260   switch (obj->type) {
2261     case CMP_TYPE_POSITIVE_FIXNUM:
2262     case CMP_TYPE_UINT8:
2263     case CMP_TYPE_UINT16:
2264     case CMP_TYPE_UINT32:
2265       return true;
2266     default:
2267       return false;
2268   }
2269 }
2270 
cmp_object_is_ulong(cmp_object_t * obj)2271 bool cmp_object_is_ulong(cmp_object_t *obj) {
2272   switch (obj->type) {
2273     case CMP_TYPE_POSITIVE_FIXNUM:
2274     case CMP_TYPE_UINT8:
2275     case CMP_TYPE_UINT16:
2276     case CMP_TYPE_UINT32:
2277     case CMP_TYPE_UINT64:
2278       return true;
2279     default:
2280       return false;
2281   }
2282 }
2283 
cmp_object_is_uinteger(cmp_object_t * obj)2284 bool cmp_object_is_uinteger(cmp_object_t *obj) {
2285   return cmp_object_is_ulong(obj);
2286 }
2287 
cmp_object_is_float(cmp_object_t * obj)2288 bool cmp_object_is_float(cmp_object_t *obj) {
2289   if (obj->type == CMP_TYPE_FLOAT)
2290     return true;
2291 
2292   return false;
2293 }
2294 
cmp_object_is_double(cmp_object_t * obj)2295 bool cmp_object_is_double(cmp_object_t *obj) {
2296   if (obj->type == CMP_TYPE_DOUBLE)
2297     return true;
2298 
2299   return false;
2300 }
2301 
cmp_object_is_nil(cmp_object_t * obj)2302 bool cmp_object_is_nil(cmp_object_t *obj) {
2303   if (obj->type == CMP_TYPE_NIL)
2304     return true;
2305 
2306   return false;
2307 }
2308 
cmp_object_is_bool(cmp_object_t * obj)2309 bool cmp_object_is_bool(cmp_object_t *obj) {
2310   if (obj->type == CMP_TYPE_BOOLEAN)
2311     return true;
2312 
2313   return false;
2314 }
2315 
cmp_object_is_str(cmp_object_t * obj)2316 bool cmp_object_is_str(cmp_object_t *obj) {
2317   switch (obj->type) {
2318     case CMP_TYPE_FIXSTR:
2319     case CMP_TYPE_STR8:
2320     case CMP_TYPE_STR16:
2321     case CMP_TYPE_STR32:
2322       return true;
2323     default:
2324       return false;
2325   }
2326 }
2327 
cmp_object_is_bin(cmp_object_t * obj)2328 bool cmp_object_is_bin(cmp_object_t *obj) {
2329   switch (obj->type) {
2330     case CMP_TYPE_BIN8:
2331     case CMP_TYPE_BIN16:
2332     case CMP_TYPE_BIN32:
2333       return true;
2334     default:
2335       return false;
2336   }
2337 }
2338 
cmp_object_is_array(cmp_object_t * obj)2339 bool cmp_object_is_array(cmp_object_t *obj) {
2340   switch (obj->type) {
2341     case CMP_TYPE_FIXARRAY:
2342     case CMP_TYPE_ARRAY16:
2343     case CMP_TYPE_ARRAY32:
2344       return true;
2345     default:
2346       return false;
2347   }
2348 }
2349 
cmp_object_is_map(cmp_object_t * obj)2350 bool cmp_object_is_map(cmp_object_t *obj) {
2351   switch (obj->type) {
2352     case CMP_TYPE_FIXMAP:
2353     case CMP_TYPE_MAP16:
2354     case CMP_TYPE_MAP32:
2355       return true;
2356     default:
2357       return false;
2358   }
2359 }
2360 
cmp_object_is_ext(cmp_object_t * obj)2361 bool cmp_object_is_ext(cmp_object_t *obj) {
2362   switch (obj->type) {
2363     case CMP_TYPE_FIXEXT1:
2364     case CMP_TYPE_FIXEXT2:
2365     case CMP_TYPE_FIXEXT4:
2366     case CMP_TYPE_FIXEXT8:
2367     case CMP_TYPE_FIXEXT16:
2368     case CMP_TYPE_EXT8:
2369     case CMP_TYPE_EXT16:
2370     case CMP_TYPE_EXT32:
2371       return true;
2372     default:
2373       return false;
2374   }
2375 }
2376 
cmp_object_as_char(cmp_object_t * obj,int8_t * c)2377 bool cmp_object_as_char(cmp_object_t *obj, int8_t *c) {
2378   switch (obj->type) {
2379     case CMP_TYPE_POSITIVE_FIXNUM:
2380     case CMP_TYPE_NEGATIVE_FIXNUM:
2381     case CMP_TYPE_SINT8:
2382       *c = obj->as.s8;
2383       return true;
2384     case CMP_TYPE_UINT8:
2385       if (obj->as.u8 <= 127) {
2386         *c = obj->as.s8;
2387         return true;
2388       }
2389   }
2390 
2391   return false;
2392 }
2393 
cmp_object_as_short(cmp_object_t * obj,int16_t * s)2394 bool cmp_object_as_short(cmp_object_t *obj, int16_t *s) {
2395   switch (obj->type) {
2396     case CMP_TYPE_POSITIVE_FIXNUM:
2397     case CMP_TYPE_NEGATIVE_FIXNUM:
2398     case CMP_TYPE_SINT8:
2399       *s = obj->as.s8;
2400       return true;
2401     case CMP_TYPE_UINT8:
2402       *s = obj->as.u8;
2403       return true;
2404     case CMP_TYPE_SINT16:
2405       *s = obj->as.s16;
2406       return true;
2407     case CMP_TYPE_UINT16:
2408       if (obj->as.u16 <= 32767) {
2409         *s = obj->as.u16;
2410         return true;
2411       }
2412   }
2413 
2414   return false;
2415 }
2416 
cmp_object_as_int(cmp_object_t * obj,int32_t * i)2417 bool cmp_object_as_int(cmp_object_t *obj, int32_t *i) {
2418   switch (obj->type) {
2419     case CMP_TYPE_POSITIVE_FIXNUM:
2420     case CMP_TYPE_NEGATIVE_FIXNUM:
2421     case CMP_TYPE_SINT8:
2422       *i = obj->as.s8;
2423       return true;
2424     case CMP_TYPE_UINT8:
2425       *i = obj->as.u8;
2426       return true;
2427     case CMP_TYPE_SINT16:
2428       *i = obj->as.s16;
2429       return true;
2430     case CMP_TYPE_UINT16:
2431       *i = obj->as.u16;
2432       return true;
2433     case CMP_TYPE_SINT32:
2434       *i = obj->as.s32;
2435       return true;
2436     case CMP_TYPE_UINT32:
2437       if (obj->as.u32 <= 2147483647) {
2438         *i = obj->as.u32;
2439         return true;
2440       }
2441   }
2442 
2443   return false;
2444 }
2445 
cmp_object_as_long(cmp_object_t * obj,int64_t * d)2446 bool cmp_object_as_long(cmp_object_t *obj, int64_t *d) {
2447   switch (obj->type) {
2448     case CMP_TYPE_POSITIVE_FIXNUM:
2449     case CMP_TYPE_NEGATIVE_FIXNUM:
2450     case CMP_TYPE_SINT8:
2451       *d = obj->as.s8;
2452       return true;
2453     case CMP_TYPE_UINT8:
2454       *d = obj->as.u8;
2455       return true;
2456     case CMP_TYPE_SINT16:
2457       *d = obj->as.s16;
2458       return true;
2459     case CMP_TYPE_UINT16:
2460       *d = obj->as.u16;
2461       return true;
2462     case CMP_TYPE_SINT32:
2463       *d = obj->as.s32;
2464       return true;
2465     case CMP_TYPE_UINT32:
2466       *d = obj->as.u32;
2467       return true;
2468     case CMP_TYPE_SINT64:
2469       *d = obj->as.s64;
2470       return true;
2471     case CMP_TYPE_UINT64:
2472       if (obj->as.u64 <= 9223372036854775807) {
2473         *d = obj->as.u64;
2474         return true;
2475       }
2476   }
2477 
2478   return false;
2479 }
2480 
cmp_object_as_sinteger(cmp_object_t * obj,int64_t * d)2481 bool cmp_object_as_sinteger(cmp_object_t *obj, int64_t *d) {
2482   return cmp_object_as_long(obj, d);
2483 }
2484 
cmp_object_as_uchar(cmp_object_t * obj,uint8_t * c)2485 bool cmp_object_as_uchar(cmp_object_t *obj, uint8_t *c) {
2486   switch (obj->type) {
2487     case CMP_TYPE_POSITIVE_FIXNUM:
2488     case CMP_TYPE_UINT8:
2489       *c = obj->as.u8;
2490       return true;
2491   }
2492 
2493   return false;
2494 }
2495 
cmp_object_as_ushort(cmp_object_t * obj,uint16_t * s)2496 bool cmp_object_as_ushort(cmp_object_t *obj, uint16_t *s) {
2497   switch (obj->type) {
2498     case CMP_TYPE_POSITIVE_FIXNUM:
2499     case CMP_TYPE_UINT8:
2500       *s = obj->as.u8;
2501       return true;
2502     case CMP_TYPE_UINT16:
2503       *s = obj->as.u16;
2504       return true;
2505   }
2506 
2507   return false;
2508 }
2509 
cmp_object_as_uint(cmp_object_t * obj,uint32_t * i)2510 bool cmp_object_as_uint(cmp_object_t *obj, uint32_t *i) {
2511   switch (obj->type) {
2512     case CMP_TYPE_POSITIVE_FIXNUM:
2513     case CMP_TYPE_UINT8:
2514       *i = obj->as.u8;
2515       return true;
2516     case CMP_TYPE_UINT16:
2517       *i = obj->as.u16;
2518       return true;
2519     case CMP_TYPE_UINT32:
2520       *i = obj->as.u32;
2521       return true;
2522   }
2523 
2524   return false;
2525 }
2526 
cmp_object_as_ulong(cmp_object_t * obj,uint64_t * u)2527 bool cmp_object_as_ulong(cmp_object_t *obj, uint64_t *u) {
2528   switch (obj->type) {
2529     case CMP_TYPE_POSITIVE_FIXNUM:
2530     case CMP_TYPE_UINT8:
2531       *u = obj->as.u8;
2532       return true;
2533     case CMP_TYPE_UINT16:
2534       *u = obj->as.u16;
2535       return true;
2536     case CMP_TYPE_UINT32:
2537       *u = obj->as.u32;
2538       return true;
2539     case CMP_TYPE_UINT64:
2540       *u = obj->as.u64;
2541       return true;
2542   }
2543 
2544   return false;
2545 }
2546 
cmp_object_as_uinteger(cmp_object_t * obj,uint64_t * d)2547 bool cmp_object_as_uinteger(cmp_object_t *obj, uint64_t *d) {
2548   return cmp_object_as_ulong(obj, d);
2549 }
2550 
cmp_object_as_float(cmp_object_t * obj,float * f)2551 bool cmp_object_as_float(cmp_object_t *obj, float *f) {
2552   if (obj->type == CMP_TYPE_FLOAT) {
2553     *f = obj->as.flt;
2554     return true;
2555   }
2556 
2557   return false;
2558 }
2559 
cmp_object_as_double(cmp_object_t * obj,double * d)2560 bool cmp_object_as_double(cmp_object_t *obj, double *d) {
2561   if (obj->type == CMP_TYPE_DOUBLE) {
2562     *d = obj->as.dbl;
2563     return true;
2564   }
2565 
2566   return false;
2567 }
2568 
cmp_object_as_bool(cmp_object_t * obj,bool * b)2569 bool cmp_object_as_bool(cmp_object_t *obj, bool *b) {
2570   if (obj->type == CMP_TYPE_BOOLEAN) {
2571     if (obj->as.boolean)
2572       *b = true;
2573     else
2574       *b = false;
2575 
2576     return true;
2577   }
2578 
2579   return false;
2580 }
2581 
cmp_object_as_str(cmp_object_t * obj,uint32_t * size)2582 bool cmp_object_as_str(cmp_object_t *obj, uint32_t *size) {
2583   switch (obj->type) {
2584     case CMP_TYPE_FIXSTR:
2585     case CMP_TYPE_STR8:
2586     case CMP_TYPE_STR16:
2587     case CMP_TYPE_STR32:
2588       *size = obj->as.str_size;
2589       return true;
2590   }
2591 
2592   return false;
2593 }
2594 
cmp_object_as_bin(cmp_object_t * obj,uint32_t * size)2595 bool cmp_object_as_bin(cmp_object_t *obj, uint32_t *size) {
2596   switch (obj->type) {
2597     case CMP_TYPE_BIN8:
2598     case CMP_TYPE_BIN16:
2599     case CMP_TYPE_BIN32:
2600       *size = obj->as.bin_size;
2601       return true;
2602   }
2603 
2604   return false;
2605 }
2606 
cmp_object_as_array(cmp_object_t * obj,uint32_t * size)2607 bool cmp_object_as_array(cmp_object_t *obj, uint32_t *size) {
2608   switch (obj->type) {
2609     case CMP_TYPE_FIXARRAY:
2610     case CMP_TYPE_ARRAY16:
2611     case CMP_TYPE_ARRAY32:
2612       *size = obj->as.array_size;
2613       return true;
2614   }
2615 
2616   return false;
2617 }
2618 
cmp_object_as_map(cmp_object_t * obj,uint32_t * size)2619 bool cmp_object_as_map(cmp_object_t *obj, uint32_t *size) {
2620   switch (obj->type) {
2621     case CMP_TYPE_FIXMAP:
2622     case CMP_TYPE_MAP16:
2623     case CMP_TYPE_MAP32:
2624       *size = obj->as.map_size;
2625       return true;
2626   }
2627 
2628   return false;
2629 }
2630 
cmp_object_as_ext(cmp_object_t * obj,int8_t * type,uint32_t * size)2631 bool cmp_object_as_ext(cmp_object_t *obj, int8_t *type, uint32_t *size) {
2632   switch (obj->type) {
2633     case CMP_TYPE_FIXEXT1:
2634     case CMP_TYPE_FIXEXT2:
2635     case CMP_TYPE_FIXEXT4:
2636     case CMP_TYPE_FIXEXT8:
2637     case CMP_TYPE_FIXEXT16:
2638     case CMP_TYPE_EXT8:
2639     case CMP_TYPE_EXT16:
2640     case CMP_TYPE_EXT32:
2641       *type = obj->as.ext.type;
2642       *size = obj->as.ext.size;
2643       return true;
2644   }
2645 
2646   return false;
2647 }
2648 
2649 /* vi: set et ts=2 sw=2: */
2650 
2651