1 /*
2 The MIT License (MIT)
3 
4 Copyright (c) 2017 Charles Gunyon
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24 
25 #include <stdbool.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 
29 #include "cmp.h"
30 
31 static const uint32_t version = 17;
32 static const uint32_t mp_version = 5;
33 
34 enum {
35   POSITIVE_FIXNUM_MARKER = 0x00,
36   FIXMAP_MARKER          = 0x80,
37   FIXARRAY_MARKER        = 0x90,
38   FIXSTR_MARKER          = 0xA0,
39   NIL_MARKER             = 0xC0,
40   FALSE_MARKER           = 0xC2,
41   TRUE_MARKER            = 0xC3,
42   BIN8_MARKER            = 0xC4,
43   BIN16_MARKER           = 0xC5,
44   BIN32_MARKER           = 0xC6,
45   EXT8_MARKER            = 0xC7,
46   EXT16_MARKER           = 0xC8,
47   EXT32_MARKER           = 0xC9,
48   FLOAT_MARKER           = 0xCA,
49   DOUBLE_MARKER          = 0xCB,
50   U8_MARKER              = 0xCC,
51   U16_MARKER             = 0xCD,
52   U32_MARKER             = 0xCE,
53   U64_MARKER             = 0xCF,
54   S8_MARKER              = 0xD0,
55   S16_MARKER             = 0xD1,
56   S32_MARKER             = 0xD2,
57   S64_MARKER             = 0xD3,
58   FIXEXT1_MARKER         = 0xD4,
59   FIXEXT2_MARKER         = 0xD5,
60   FIXEXT4_MARKER         = 0xD6,
61   FIXEXT8_MARKER         = 0xD7,
62   FIXEXT16_MARKER        = 0xD8,
63   STR8_MARKER            = 0xD9,
64   STR16_MARKER           = 0xDA,
65   STR32_MARKER           = 0xDB,
66   ARRAY16_MARKER         = 0xDC,
67   ARRAY32_MARKER         = 0xDD,
68   MAP16_MARKER           = 0xDE,
69   MAP32_MARKER           = 0xDF,
70   NEGATIVE_FIXNUM_MARKER = 0xE0
71 };
72 
73 enum {
74   FIXARRAY_SIZE = 0xF,
75   FIXMAP_SIZE   = 0xF,
76   FIXSTR_SIZE   = 0x1F
77 };
78 
79 enum {
80   ERROR_NONE,
81   STR_DATA_LENGTH_TOO_LONG_ERROR,
82   BIN_DATA_LENGTH_TOO_LONG_ERROR,
83   ARRAY_LENGTH_TOO_LONG_ERROR,
84   MAP_LENGTH_TOO_LONG_ERROR,
85   INPUT_VALUE_TOO_LARGE_ERROR,
86   FIXED_VALUE_WRITING_ERROR,
87   TYPE_MARKER_READING_ERROR,
88   TYPE_MARKER_WRITING_ERROR,
89   DATA_READING_ERROR,
90   DATA_WRITING_ERROR,
91   EXT_TYPE_READING_ERROR,
92   EXT_TYPE_WRITING_ERROR,
93   INVALID_TYPE_ERROR,
94   LENGTH_READING_ERROR,
95   LENGTH_WRITING_ERROR,
96   SKIP_DEPTH_LIMIT_EXCEEDED_ERROR,
97   INTERNAL_ERROR,
98   ERROR_MAX
99 };
100 
101 const char *cmp_error_messages[ERROR_MAX + 1] = {
102   "No Error",
103   "Specified string data length is too long (> 0xFFFFFFFF)",
104   "Specified binary data length is too long (> 0xFFFFFFFF)",
105   "Specified array length is too long (> 0xFFFFFFFF)",
106   "Specified map length is too long (> 0xFFFFFFFF)",
107   "Input value is too large",
108   "Error writing fixed value",
109   "Error reading type marker",
110   "Error writing type marker",
111   "Error reading packed data",
112   "Error writing packed data",
113   "Error reading ext type",
114   "Error writing ext type",
115   "Invalid type",
116   "Error reading size",
117   "Error writing size",
118   "Depth limit exceeded while skipping",
119   "Internal error",
120   "Max Error"
121 };
122 
123 static const int32_t _i = 1;
124 #define is_bigendian() ((*(char *)&_i) == 0)
125 
be16(uint16_t x)126 static uint16_t be16(uint16_t x) {
127   char *b = (char *)&x;
128 
129   if (!is_bigendian()) {
130     char swap = 0;
131 
132     swap = b[0];
133     b[0] = b[1];
134     b[1] = swap;
135   }
136 
137   return x;
138 }
139 
be32(uint32_t x)140 static uint32_t be32(uint32_t x) {
141   char *b = (char *)&x;
142 
143   if (!is_bigendian()) {
144     char swap = 0;
145 
146     swap = b[0];
147     b[0] = b[3];
148     b[3] = swap;
149 
150     swap = b[1];
151     b[1] = b[2];
152     b[2] = swap;
153   }
154 
155   return x;
156 }
157 
be64(uint64_t x)158 static uint64_t be64(uint64_t x) {
159   char *b = (char *)&x;
160 
161   if (!is_bigendian()) {
162     char swap = 0;
163 
164     swap = b[0];
165     b[0] = b[7];
166     b[7] = swap;
167 
168     swap = b[1];
169     b[1] = b[6];
170     b[6] = swap;
171 
172     swap = b[2];
173     b[2] = b[5];
174     b[5] = swap;
175 
176     swap = b[3];
177     b[3] = b[4];
178     b[4] = swap;
179   }
180 
181   return x;
182 }
183 
decode_befloat(char * b)184 static float decode_befloat(char *b) {
185   float f = 0.;
186   char *fb = (char *)&f;
187 
188   if (!is_bigendian()) {
189     fb[0] = b[3];
190     fb[1] = b[2];
191     fb[2] = b[1];
192     fb[3] = b[0];
193   }
194 
195   return f;
196 }
197 
decode_bedouble(char * b)198 static double decode_bedouble(char *b) {
199   double d = 0.;
200   char *db = (char *)&d;
201 
202   if (!is_bigendian()) {
203     db[0] = b[7];
204     db[1] = b[6];
205     db[2] = b[5];
206     db[3] = b[4];
207     db[4] = b[3];
208     db[5] = b[2];
209     db[6] = b[1];
210     db[7] = b[0];
211   }
212 
213   return d;
214 }
215 
read_byte(cmp_ctx_t * ctx,uint8_t * x)216 static bool read_byte(cmp_ctx_t *ctx, uint8_t *x) {
217   return ctx->read(ctx, x, sizeof(uint8_t));
218 }
219 
write_byte(cmp_ctx_t * ctx,uint8_t x)220 static bool write_byte(cmp_ctx_t *ctx, uint8_t x) {
221   return (ctx->write(ctx, &x, sizeof(uint8_t)) == (sizeof(uint8_t)));
222 }
223 
skip_bytes(cmp_ctx_t * ctx,size_t count)224 static bool skip_bytes(cmp_ctx_t *ctx, size_t count) {
225   if (ctx->skip) {
226     return ctx->skip(ctx, count);
227   }
228   else {
229     uint8_t floor;
230     size_t i;
231 
232     for (i = 0; i < count; i++) {
233       if (!ctx->read(ctx, &floor, sizeof(uint8_t))) {
234         return false;
235       }
236     }
237 
238     return true;
239   }
240 }
241 
read_type_marker(cmp_ctx_t * ctx,uint8_t * marker)242 static bool read_type_marker(cmp_ctx_t *ctx, uint8_t *marker) {
243   if (read_byte(ctx, marker)) {
244     return true;
245   }
246 
247   ctx->error = TYPE_MARKER_READING_ERROR;
248   return false;
249 }
250 
write_type_marker(cmp_ctx_t * ctx,uint8_t marker)251 static bool write_type_marker(cmp_ctx_t *ctx, uint8_t marker) {
252   if (write_byte(ctx, marker))
253     return true;
254 
255   ctx->error = TYPE_MARKER_WRITING_ERROR;
256   return false;
257 }
258 
write_fixed_value(cmp_ctx_t * ctx,uint8_t value)259 static bool write_fixed_value(cmp_ctx_t *ctx, uint8_t value) {
260   if (write_byte(ctx, value))
261     return true;
262 
263   ctx->error = FIXED_VALUE_WRITING_ERROR;
264   return false;
265 }
266 
type_marker_to_cmp_type(uint8_t type_marker,uint8_t * cmp_type)267 static bool type_marker_to_cmp_type(uint8_t type_marker, uint8_t *cmp_type) {
268   if (type_marker <= 0x7F) {
269     *cmp_type = CMP_TYPE_POSITIVE_FIXNUM;
270     return true;
271   }
272 
273   if (type_marker <= 0x8F) {
274     *cmp_type = CMP_TYPE_FIXMAP;
275     return true;
276   }
277 
278   if (type_marker <= 0x9F) {
279     *cmp_type = CMP_TYPE_FIXARRAY;
280     return true;
281   }
282 
283   if (type_marker <= 0xBF) {
284     *cmp_type = CMP_TYPE_FIXSTR;
285     return true;
286   }
287 
288   if (type_marker >= 0xE0) {
289     *cmp_type = CMP_TYPE_NEGATIVE_FIXNUM;
290     return true;
291   }
292 
293   switch (type_marker) {
294     case NIL_MARKER:
295       *cmp_type = CMP_TYPE_NIL;
296       return true;
297     case FALSE_MARKER:
298       *cmp_type = CMP_TYPE_BOOLEAN;
299       return true;
300     case TRUE_MARKER:
301       *cmp_type = CMP_TYPE_BOOLEAN;
302       return true;
303     case BIN8_MARKER:
304       *cmp_type = CMP_TYPE_BIN8;
305       return true;
306     case BIN16_MARKER:
307       *cmp_type = CMP_TYPE_BIN16;
308       return true;
309     case BIN32_MARKER:
310       *cmp_type = CMP_TYPE_BIN32;
311       return true;
312     case EXT8_MARKER:
313       *cmp_type = CMP_TYPE_EXT8;
314       return true;
315     case EXT16_MARKER:
316       *cmp_type = CMP_TYPE_EXT16;
317       return true;
318     case EXT32_MARKER:
319       *cmp_type = CMP_TYPE_EXT32;
320       return true;
321     case FLOAT_MARKER:
322       *cmp_type = CMP_TYPE_FLOAT;
323       return true;
324     case DOUBLE_MARKER:
325       *cmp_type = CMP_TYPE_DOUBLE;
326       return true;
327     case U8_MARKER:
328       *cmp_type = CMP_TYPE_UINT8;
329       return true;
330     case U16_MARKER:
331       *cmp_type = CMP_TYPE_UINT16;
332       return true;
333     case U32_MARKER:
334       *cmp_type = CMP_TYPE_UINT32;
335       return true;
336     case U64_MARKER:
337       *cmp_type = CMP_TYPE_UINT64;
338       return true;
339     case S8_MARKER:
340       *cmp_type = CMP_TYPE_SINT8;
341       return true;
342     case S16_MARKER:
343       *cmp_type = CMP_TYPE_SINT16;
344       return true;
345     case S32_MARKER:
346       *cmp_type = CMP_TYPE_SINT32;
347       return true;
348     case S64_MARKER:
349       *cmp_type = CMP_TYPE_SINT64;
350       return true;
351     case FIXEXT1_MARKER:
352       *cmp_type = CMP_TYPE_FIXEXT1;
353       return true;
354     case FIXEXT2_MARKER:
355       *cmp_type = CMP_TYPE_FIXEXT2;
356       return true;
357     case FIXEXT4_MARKER:
358       *cmp_type = CMP_TYPE_FIXEXT4;
359       return true;
360     case FIXEXT8_MARKER:
361       *cmp_type = CMP_TYPE_FIXEXT8;
362       return true;
363     case FIXEXT16_MARKER:
364       *cmp_type = CMP_TYPE_FIXEXT16;
365       return true;
366     case STR8_MARKER:
367       *cmp_type = CMP_TYPE_STR8;
368       return true;
369     case STR16_MARKER:
370       *cmp_type = CMP_TYPE_STR16;
371       return true;
372     case STR32_MARKER:
373       *cmp_type = CMP_TYPE_STR32;
374       return true;
375     case ARRAY16_MARKER:
376       *cmp_type = CMP_TYPE_ARRAY16;
377       return true;
378     case ARRAY32_MARKER:
379       *cmp_type = CMP_TYPE_ARRAY32;
380       return true;
381     case MAP16_MARKER:
382       *cmp_type = CMP_TYPE_MAP16;
383       return true;
384     case MAP32_MARKER:
385       *cmp_type = CMP_TYPE_MAP32;
386       return true;
387     default:
388       return false;
389   }
390 }
391 
read_type_size(cmp_ctx_t * ctx,uint8_t type_marker,uint8_t cmp_type,uint32_t * size)392 static bool read_type_size(cmp_ctx_t *ctx, uint8_t type_marker,
393                                            uint8_t cmp_type,
394                                            uint32_t *size) {
395   uint8_t u8temp = 0;
396   uint16_t u16temp = 0;
397   uint32_t u32temp = 0;
398 
399   switch (cmp_type) {
400     case CMP_TYPE_POSITIVE_FIXNUM:
401       *size = 0;
402       return true;
403     case CMP_TYPE_FIXMAP:
404       *size = (type_marker & FIXMAP_SIZE);
405       return true;
406     case CMP_TYPE_FIXARRAY:
407       *size = (type_marker & FIXARRAY_SIZE);
408       return true;
409     case CMP_TYPE_FIXSTR:
410       *size = (type_marker & FIXSTR_SIZE);
411       return true;
412     case CMP_TYPE_NIL:
413       *size = 0;
414       return true;
415     case CMP_TYPE_BOOLEAN:
416       *size = 0;
417       return true;
418     case CMP_TYPE_BIN8:
419       if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
420         ctx->error = LENGTH_READING_ERROR;
421         return false;
422       }
423       *size = u8temp;
424       return true;
425     case CMP_TYPE_BIN16:
426       if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
427         ctx->error = LENGTH_READING_ERROR;
428         return false;
429       }
430       *size = be16(u16temp);
431       return true;
432     case CMP_TYPE_BIN32:
433       if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
434         ctx->error = LENGTH_READING_ERROR;
435         return false;
436       }
437       *size = be32(u32temp);
438       return true;
439     case CMP_TYPE_EXT8:
440       if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
441         ctx->error = LENGTH_READING_ERROR;
442         return false;
443       }
444       *size = u8temp;
445       return true;
446     case CMP_TYPE_EXT16:
447       if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
448         ctx->error = LENGTH_READING_ERROR;
449         return false;
450       }
451       *size = be16(u16temp);
452       return true;
453     case CMP_TYPE_EXT32:
454       if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
455         ctx->error = LENGTH_READING_ERROR;
456         return false;
457       }
458       *size = be32(u32temp);
459       return true;
460     case CMP_TYPE_FLOAT:
461       *size = 4;
462       return true;
463     case CMP_TYPE_DOUBLE:
464       *size = 8;
465       return true;
466     case CMP_TYPE_UINT8:
467       *size = 1;
468       return true;
469     case CMP_TYPE_UINT16:
470       *size = 2;
471       return true;
472     case CMP_TYPE_UINT32:
473       *size = 4;
474       return true;
475     case CMP_TYPE_UINT64:
476       *size = 8;
477       return true;
478     case CMP_TYPE_SINT8:
479       *size = 1;
480       return true;
481     case CMP_TYPE_SINT16:
482       *size = 2;
483       return true;
484     case CMP_TYPE_SINT32:
485       *size = 4;
486       return true;
487     case CMP_TYPE_SINT64:
488       *size = 8;
489       return true;
490     case CMP_TYPE_FIXEXT1:
491       *size = 1;
492       return true;
493     case CMP_TYPE_FIXEXT2:
494       *size = 2;
495       return true;
496     case CMP_TYPE_FIXEXT4:
497       *size = 4;
498       return true;
499     case CMP_TYPE_FIXEXT8:
500       *size = 8;
501       return true;
502     case CMP_TYPE_FIXEXT16:
503       *size = 16;
504       return true;
505     case CMP_TYPE_STR8:
506       if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
507         ctx->error = DATA_READING_ERROR;
508         return false;
509       }
510       *size = u8temp;
511       return true;
512     case CMP_TYPE_STR16:
513       if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
514         ctx->error = DATA_READING_ERROR;
515         return false;
516       }
517       *size = be16(u16temp);
518       return true;
519     case CMP_TYPE_STR32:
520       if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
521         ctx->error = DATA_READING_ERROR;
522         return false;
523       }
524       *size = be32(u32temp);
525       return true;
526     case CMP_TYPE_ARRAY16:
527       if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
528         ctx->error = DATA_READING_ERROR;
529         return false;
530       }
531       *size = be16(u16temp);
532       return true;
533     case CMP_TYPE_ARRAY32:
534       if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
535         ctx->error = DATA_READING_ERROR;
536         return false;
537       }
538       *size = be32(u32temp);
539       return true;
540     case CMP_TYPE_MAP16:
541       if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
542         ctx->error = DATA_READING_ERROR;
543         return false;
544       }
545       *size = be16(u16temp);
546       return true;
547     case CMP_TYPE_MAP32:
548       if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
549         ctx->error = DATA_READING_ERROR;
550         return false;
551       }
552       *size = be32(u32temp);
553       return true;
554     case CMP_TYPE_NEGATIVE_FIXNUM:
555       *size = 0;
556       return true;
557     default:
558       ctx->error = INVALID_TYPE_ERROR;
559       return false;
560   }
561 }
562 
read_obj_data(cmp_ctx_t * ctx,uint8_t type_marker,cmp_object_t * obj)563 static bool read_obj_data(cmp_ctx_t *ctx, uint8_t type_marker,
564                                           cmp_object_t *obj) {
565   switch (obj->type) {
566     case CMP_TYPE_POSITIVE_FIXNUM:
567       obj->as.u8 = type_marker;
568       return true;
569     case CMP_TYPE_NEGATIVE_FIXNUM:
570       obj->as.s8 = type_marker;
571       return true;
572     case CMP_TYPE_NIL:
573       obj->as.u8 = 0;
574       return true;
575     case CMP_TYPE_BOOLEAN:
576       switch (type_marker) {
577         case TRUE_MARKER:
578           obj->as.boolean = true;
579           return true;
580         case FALSE_MARKER:
581           obj->as.boolean = false;
582           return true;
583         default:
584           break;
585       }
586       ctx->error = INTERNAL_ERROR;
587       return false;
588     case CMP_TYPE_UINT8:
589       if (!ctx->read(ctx, &obj->as.u8, sizeof(uint8_t))) {
590         ctx->error = DATA_READING_ERROR;
591         return false;
592       }
593       return true;
594     case CMP_TYPE_UINT16:
595       if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
596         ctx->error = DATA_READING_ERROR;
597         return false;
598       }
599       obj->as.u16 = be16(obj->as.u16);
600       return true;
601     case CMP_TYPE_UINT32:
602       if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
603         ctx->error = DATA_READING_ERROR;
604         return false;
605       }
606       obj->as.u32 = be32(obj->as.u32);
607       return true;
608     case CMP_TYPE_UINT64:
609       if (!ctx->read(ctx, &obj->as.u64, sizeof(uint64_t))) {
610         ctx->error = DATA_READING_ERROR;
611         return false;
612       }
613       obj->as.u64 = be64(obj->as.u64);
614       return true;
615     case CMP_TYPE_SINT8:
616       if (!ctx->read(ctx, &obj->as.s8, sizeof(int8_t))) {
617         ctx->error = DATA_READING_ERROR;
618         return false;
619       }
620       return true;
621     case CMP_TYPE_SINT16:
622       if (!ctx->read(ctx, &obj->as.s16, sizeof(int16_t))) {
623         ctx->error = DATA_READING_ERROR;
624         return false;
625       }
626       obj->as.s16 = be16(obj->as.s16);
627       return true;
628     case CMP_TYPE_SINT32:
629       if (!ctx->read(ctx, &obj->as.s32, sizeof(int32_t))) {
630         ctx->error = DATA_READING_ERROR;
631         return false;
632       }
633       obj->as.s32 = be32(obj->as.s32);
634       return true;
635     case CMP_TYPE_SINT64:
636       if (!ctx->read(ctx, &obj->as.s64, sizeof(int64_t))) {
637         ctx->error = DATA_READING_ERROR;
638         return false;
639       }
640       obj->as.s64 = be64(obj->as.s64);
641       return true;
642     case CMP_TYPE_FLOAT:
643     {
644       char bytes[4];
645 
646       if (!ctx->read(ctx, bytes, 4)) {
647         ctx->error = DATA_READING_ERROR;
648         return false;
649       }
650       obj->as.flt = decode_befloat(bytes);
651       return true;
652     }
653     case CMP_TYPE_DOUBLE:
654     {
655       char bytes[8];
656 
657       if (!ctx->read(ctx, bytes, 8)) {
658         ctx->error = DATA_READING_ERROR;
659         return false;
660       }
661       obj->as.dbl = decode_bedouble(bytes);
662       return true;
663     }
664     case CMP_TYPE_BIN8:
665     case CMP_TYPE_BIN16:
666     case CMP_TYPE_BIN32:
667       return read_type_size(ctx, type_marker, obj->type, &obj->as.bin_size);
668     case CMP_TYPE_FIXSTR:
669     case CMP_TYPE_STR8:
670     case CMP_TYPE_STR16:
671     case CMP_TYPE_STR32:
672       return read_type_size(ctx, type_marker, obj->type, &obj->as.str_size);
673     case CMP_TYPE_FIXARRAY:
674     case CMP_TYPE_ARRAY16:
675     case CMP_TYPE_ARRAY32:
676       return read_type_size(ctx, type_marker, obj->type, &obj->as.array_size);
677     case CMP_TYPE_FIXMAP:
678     case CMP_TYPE_MAP16:
679     case CMP_TYPE_MAP32:
680       return read_type_size(ctx, type_marker, obj->type, &obj->as.map_size);
681     case CMP_TYPE_FIXEXT1:
682       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
683         ctx->error = EXT_TYPE_READING_ERROR;
684         return false;
685       }
686       obj->as.ext.size = 1;
687       return true;
688     case CMP_TYPE_FIXEXT2:
689       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
690         ctx->error = EXT_TYPE_READING_ERROR;
691         return false;
692       }
693       obj->as.ext.size = 2;
694       return true;
695     case CMP_TYPE_FIXEXT4:
696       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
697         ctx->error = EXT_TYPE_READING_ERROR;
698         return false;
699       }
700       obj->as.ext.size = 4;
701       return true;
702     case CMP_TYPE_FIXEXT8:
703       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
704         ctx->error = EXT_TYPE_READING_ERROR;
705         return false;
706       }
707       obj->as.ext.size = 8;
708       return true;
709     case CMP_TYPE_FIXEXT16:
710       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
711         ctx->error = EXT_TYPE_READING_ERROR;
712         return false;
713       }
714       obj->as.ext.size = 16;
715       return true;
716     case CMP_TYPE_EXT8:
717       if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
718         return false;
719       }
720       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
721         ctx->error = EXT_TYPE_READING_ERROR;
722         return false;
723       }
724       return true;
725     case CMP_TYPE_EXT16:
726       if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
727         return false;
728       }
729       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
730         ctx->error = EXT_TYPE_READING_ERROR;
731         return false;
732       }
733       obj->as.ext.type = obj->as.ext.type;
734       return true;
735     case CMP_TYPE_EXT32:
736       if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
737         return false;
738       }
739       if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
740         ctx->error = EXT_TYPE_READING_ERROR;
741         return false;
742       }
743       obj->as.ext.type = obj->as.ext.type;
744       return true;
745     default:
746       break;
747   }
748 
749   ctx->error = INVALID_TYPE_ERROR;
750   return false;
751 }
752 
cmp_init(cmp_ctx_t * ctx,void * buf,cmp_reader read,cmp_skipper skip,cmp_writer write)753 void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read,
754                                          cmp_skipper skip,
755                                          cmp_writer write) {
756   ctx->error = ERROR_NONE;
757   ctx->buf = buf;
758   ctx->read = read;
759   ctx->skip = skip;
760   ctx->write = write;
761 }
762 
cmp_version(void)763 uint32_t cmp_version(void) {
764   return version;
765 }
766 
cmp_mp_version(void)767 uint32_t cmp_mp_version(void) {
768   return mp_version;
769 }
770 
cmp_strerror(cmp_ctx_t * ctx)771 const char* cmp_strerror(cmp_ctx_t *ctx) {
772   if (ctx->error > ERROR_NONE && ctx->error < ERROR_MAX)
773     return cmp_error_messages[ctx->error];
774 
775   return "";
776 }
777 
cmp_write_pfix(cmp_ctx_t * ctx,uint8_t c)778 bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c) {
779   if (c <= 0x7F)
780     return write_fixed_value(ctx, c);
781 
782   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
783   return false;
784 }
785 
cmp_write_nfix(cmp_ctx_t * ctx,int8_t c)786 bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) {
787   if (c >= -32 && c <= -1)
788     return write_fixed_value(ctx, c);
789 
790   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
791   return false;
792 }
793 
cmp_write_sfix(cmp_ctx_t * ctx,int8_t c)794 bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c) {
795   if (c >= 0)
796     return cmp_write_pfix(ctx, c);
797   if (c >= -32 && c <= -1)
798     return cmp_write_nfix(ctx, c);
799 
800   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
801   return false;
802 }
803 
cmp_write_s8(cmp_ctx_t * ctx,int8_t c)804 bool cmp_write_s8(cmp_ctx_t *ctx, int8_t c) {
805   if (!write_type_marker(ctx, S8_MARKER))
806     return false;
807 
808   return ctx->write(ctx, &c, sizeof(int8_t));
809 }
810 
cmp_write_s16(cmp_ctx_t * ctx,int16_t s)811 bool cmp_write_s16(cmp_ctx_t *ctx, int16_t s) {
812   if (!write_type_marker(ctx, S16_MARKER))
813     return false;
814 
815   s = be16(s);
816 
817   return ctx->write(ctx, &s, sizeof(int16_t));
818 }
819 
cmp_write_s32(cmp_ctx_t * ctx,int32_t i)820 bool cmp_write_s32(cmp_ctx_t *ctx, int32_t i) {
821   if (!write_type_marker(ctx, S32_MARKER))
822     return false;
823 
824   i = be32(i);
825 
826   return ctx->write(ctx, &i, sizeof(int32_t));
827 }
828 
cmp_write_s64(cmp_ctx_t * ctx,int64_t l)829 bool cmp_write_s64(cmp_ctx_t *ctx, int64_t l) {
830   if (!write_type_marker(ctx, S64_MARKER))
831     return false;
832 
833   l = be64(l);
834 
835   return ctx->write(ctx, &l, sizeof(int64_t));
836 }
837 
cmp_write_integer(cmp_ctx_t * ctx,int64_t d)838 bool cmp_write_integer(cmp_ctx_t *ctx, int64_t d) {
839   if (d >= 0)
840     return cmp_write_uinteger(ctx, d);
841   if (d >= -32)
842     return cmp_write_nfix(ctx, (int8_t)d);
843   if (d >= -128)
844     return cmp_write_s8(ctx, (int8_t)d);
845   if (d >= -32768)
846     return cmp_write_s16(ctx, (int16_t)d);
847   if (d >= (-2147483647 - 1))
848     return cmp_write_s32(ctx, (int32_t)d);
849 
850   return cmp_write_s64(ctx, d);
851 }
852 
cmp_write_ufix(cmp_ctx_t * ctx,uint8_t c)853 bool cmp_write_ufix(cmp_ctx_t *ctx, uint8_t c) {
854   return cmp_write_pfix(ctx, c);
855 }
856 
cmp_write_u8(cmp_ctx_t * ctx,uint8_t c)857 bool cmp_write_u8(cmp_ctx_t *ctx, uint8_t c) {
858   if (!write_type_marker(ctx, U8_MARKER))
859     return false;
860 
861   return ctx->write(ctx, &c, sizeof(uint8_t));
862 }
863 
cmp_write_u16(cmp_ctx_t * ctx,uint16_t s)864 bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s) {
865   if (!write_type_marker(ctx, U16_MARKER))
866     return false;
867 
868   s = be16(s);
869 
870   return ctx->write(ctx, &s, sizeof(uint16_t));
871 }
872 
cmp_write_u32(cmp_ctx_t * ctx,uint32_t i)873 bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i) {
874   if (!write_type_marker(ctx, U32_MARKER))
875     return false;
876 
877   i = be32(i);
878 
879   return ctx->write(ctx, &i, sizeof(uint32_t));
880 }
881 
cmp_write_u64(cmp_ctx_t * ctx,uint64_t l)882 bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l) {
883   if (!write_type_marker(ctx, U64_MARKER))
884     return false;
885 
886   l = be64(l);
887 
888   return ctx->write(ctx, &l, sizeof(uint64_t));
889 }
890 
cmp_write_uinteger(cmp_ctx_t * ctx,uint64_t u)891 bool cmp_write_uinteger(cmp_ctx_t *ctx, uint64_t u) {
892   if (u <= 0x7F)
893     return cmp_write_pfix(ctx, (uint8_t)u);
894   if (u <= 0xFF)
895     return cmp_write_u8(ctx, (uint8_t)u);
896   if (u <= 0xFFFF)
897     return cmp_write_u16(ctx, (uint16_t)u);
898   if (u <= 0xFFFFFFFF)
899     return cmp_write_u32(ctx, (uint32_t)u);
900 
901   return cmp_write_u64(ctx, u);
902 }
903 
cmp_write_float(cmp_ctx_t * ctx,float f)904 bool cmp_write_float(cmp_ctx_t *ctx, float f) {
905   if (!write_type_marker(ctx, FLOAT_MARKER))
906     return false;
907 
908   /*
909    * We may need to swap the float's bytes, but we can't just swap them inside
910    * the float because the swapped bytes may not constitute a valid float.
911    * Therefore, we have to create a buffer and swap the bytes there.
912    */
913   if (!is_bigendian()) {
914     char swapped[sizeof(float)];
915     char *fbuf = (char *)&f;
916     size_t i;
917 
918     for (i = 0; i < sizeof(float); i++)
919       swapped[i] = fbuf[sizeof(float) - i - 1];
920 
921     return ctx->write(ctx, swapped, sizeof(float));
922   }
923 
924   return ctx->write(ctx, &f, sizeof(float));
925 }
926 
cmp_write_double(cmp_ctx_t * ctx,double d)927 bool cmp_write_double(cmp_ctx_t *ctx, double d) {
928   if (!write_type_marker(ctx, DOUBLE_MARKER))
929     return false;
930 
931   /* Same deal for doubles */
932   if (!is_bigendian()) {
933     char swapped[sizeof(double)];
934     char *dbuf = (char *)&d;
935     size_t i;
936 
937     for (i = 0; i < sizeof(double); i++)
938       swapped[i] = dbuf[sizeof(double) - i - 1];
939 
940     return ctx->write(ctx, swapped, sizeof(double));
941   }
942 
943   return ctx->write(ctx, &d, sizeof(double));
944 }
945 
cmp_write_decimal(cmp_ctx_t * ctx,double d)946 bool cmp_write_decimal(cmp_ctx_t *ctx, double d) {
947   float f = (float)d;
948   double df = (double)f;
949 
950   if (df == d)
951     return cmp_write_float(ctx, f);
952   else
953     return cmp_write_double(ctx, d);
954 }
955 
cmp_write_nil(cmp_ctx_t * ctx)956 bool cmp_write_nil(cmp_ctx_t *ctx) {
957   return write_type_marker(ctx, NIL_MARKER);
958 }
959 
cmp_write_true(cmp_ctx_t * ctx)960 bool cmp_write_true(cmp_ctx_t *ctx) {
961   return write_type_marker(ctx, TRUE_MARKER);
962 }
963 
cmp_write_false(cmp_ctx_t * ctx)964 bool cmp_write_false(cmp_ctx_t *ctx) {
965   return write_type_marker(ctx, FALSE_MARKER);
966 }
967 
cmp_write_bool(cmp_ctx_t * ctx,bool b)968 bool cmp_write_bool(cmp_ctx_t *ctx, bool b) {
969   if (b)
970     return cmp_write_true(ctx);
971 
972   return cmp_write_false(ctx);
973 }
974 
cmp_write_u8_as_bool(cmp_ctx_t * ctx,uint8_t b)975 bool cmp_write_u8_as_bool(cmp_ctx_t *ctx, uint8_t b) {
976   if (b)
977     return cmp_write_true(ctx);
978 
979   return cmp_write_false(ctx);
980 }
981 
cmp_write_fixstr_marker(cmp_ctx_t * ctx,uint8_t size)982 bool cmp_write_fixstr_marker(cmp_ctx_t *ctx, uint8_t size) {
983   if (size <= FIXSTR_SIZE)
984     return write_fixed_value(ctx, FIXSTR_MARKER | size);
985 
986   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
987   return false;
988 }
989 
cmp_write_fixstr(cmp_ctx_t * ctx,const char * data,uint8_t size)990 bool cmp_write_fixstr(cmp_ctx_t *ctx, const char *data, uint8_t size) {
991   if (!cmp_write_fixstr_marker(ctx, size))
992     return false;
993 
994   if (size == 0)
995     return true;
996 
997   if (ctx->write(ctx, data, size))
998     return true;
999 
1000   ctx->error = DATA_WRITING_ERROR;
1001   return false;
1002 }
1003 
cmp_write_str8_marker(cmp_ctx_t * ctx,uint8_t size)1004 bool cmp_write_str8_marker(cmp_ctx_t *ctx, uint8_t size) {
1005   if (!write_type_marker(ctx, STR8_MARKER))
1006     return false;
1007 
1008   if (ctx->write(ctx, &size, sizeof(uint8_t)))
1009     return true;
1010 
1011   ctx->error = LENGTH_WRITING_ERROR;
1012   return false;
1013 }
1014 
cmp_write_str8(cmp_ctx_t * ctx,const char * data,uint8_t size)1015 bool cmp_write_str8(cmp_ctx_t *ctx, const char *data, uint8_t size) {
1016   if (!cmp_write_str8_marker(ctx, size))
1017     return false;
1018 
1019   if (size == 0)
1020     return true;
1021 
1022   if (ctx->write(ctx, data, size))
1023     return true;
1024 
1025   ctx->error = DATA_WRITING_ERROR;
1026   return false;
1027 }
1028 
cmp_write_str16_marker(cmp_ctx_t * ctx,uint16_t size)1029 bool cmp_write_str16_marker(cmp_ctx_t *ctx, uint16_t size) {
1030   if (!write_type_marker(ctx, STR16_MARKER))
1031     return false;
1032 
1033   size = be16(size);
1034 
1035   if (ctx->write(ctx, &size, sizeof(uint16_t)))
1036     return true;
1037 
1038   ctx->error = LENGTH_WRITING_ERROR;
1039   return false;
1040 }
1041 
cmp_write_str16(cmp_ctx_t * ctx,const char * data,uint16_t size)1042 bool cmp_write_str16(cmp_ctx_t *ctx, const char *data, uint16_t size) {
1043   if (!cmp_write_str16_marker(ctx, size))
1044     return false;
1045 
1046   if (size == 0)
1047     return true;
1048 
1049   if (ctx->write(ctx, data, size))
1050     return true;
1051 
1052   ctx->error = DATA_WRITING_ERROR;
1053   return false;
1054 }
1055 
cmp_write_str32_marker(cmp_ctx_t * ctx,uint32_t size)1056 bool cmp_write_str32_marker(cmp_ctx_t *ctx, uint32_t size) {
1057   if (!write_type_marker(ctx, STR32_MARKER))
1058     return false;
1059 
1060   size = be32(size);
1061 
1062   if (ctx->write(ctx, &size, sizeof(uint32_t)))
1063     return true;
1064 
1065   ctx->error = LENGTH_WRITING_ERROR;
1066   return false;
1067 }
1068 
cmp_write_str32(cmp_ctx_t * ctx,const char * data,uint32_t size)1069 bool cmp_write_str32(cmp_ctx_t *ctx, const char *data, uint32_t size) {
1070   if (!cmp_write_str32_marker(ctx, size))
1071     return false;
1072 
1073   if (size == 0)
1074     return true;
1075 
1076   if (ctx->write(ctx, data, size))
1077     return true;
1078 
1079   ctx->error = DATA_WRITING_ERROR;
1080   return false;
1081 }
1082 
cmp_write_str_marker(cmp_ctx_t * ctx,uint32_t size)1083 bool cmp_write_str_marker(cmp_ctx_t *ctx, uint32_t size) {
1084   if (size <= FIXSTR_SIZE)
1085     return cmp_write_fixstr_marker(ctx, (uint8_t)size);
1086   if (size <= 0xFF)
1087     return cmp_write_str8_marker(ctx, (uint8_t)size);
1088   if (size <= 0xFFFF)
1089     return cmp_write_str16_marker(ctx, (uint16_t)size);
1090 
1091   return cmp_write_str32_marker(ctx, size);
1092 }
1093 
cmp_write_str_marker_v4(cmp_ctx_t * ctx,uint32_t size)1094 bool cmp_write_str_marker_v4(cmp_ctx_t *ctx, uint32_t size) {
1095   if (size <= FIXSTR_SIZE)
1096     return cmp_write_fixstr_marker(ctx, (uint8_t)size);
1097   if (size <= 0xFFFF)
1098     return cmp_write_str16_marker(ctx, (uint16_t)size);
1099 
1100   return cmp_write_str32_marker(ctx, size);
1101 }
1102 
cmp_write_str(cmp_ctx_t * ctx,const char * data,uint32_t size)1103 bool cmp_write_str(cmp_ctx_t *ctx, const char *data, uint32_t size) {
1104   if (size <= FIXSTR_SIZE)
1105     return cmp_write_fixstr(ctx, data, (uint8_t)size);
1106   if (size <= 0xFF)
1107     return cmp_write_str8(ctx, data, (uint8_t)size);
1108   if (size <= 0xFFFF)
1109     return cmp_write_str16(ctx, data, (uint16_t)size);
1110 
1111   return cmp_write_str32(ctx, data, size);
1112 }
1113 
cmp_write_str_v4(cmp_ctx_t * ctx,const char * data,uint32_t size)1114 bool cmp_write_str_v4(cmp_ctx_t *ctx, const char *data, uint32_t size) {
1115   if (size <= FIXSTR_SIZE)
1116     return cmp_write_fixstr(ctx, data, (uint8_t)size);
1117   if (size <= 0xFFFF)
1118     return cmp_write_str16(ctx, data, (uint16_t)size);
1119 
1120   return cmp_write_str32(ctx, data, size);
1121 }
1122 
cmp_write_bin8_marker(cmp_ctx_t * ctx,uint8_t size)1123 bool cmp_write_bin8_marker(cmp_ctx_t *ctx, uint8_t size) {
1124   if (!write_type_marker(ctx, BIN8_MARKER))
1125     return false;
1126 
1127   if (ctx->write(ctx, &size, sizeof(uint8_t)))
1128     return true;
1129 
1130   ctx->error = LENGTH_WRITING_ERROR;
1131   return false;
1132 }
1133 
cmp_write_bin8(cmp_ctx_t * ctx,const void * data,uint8_t size)1134 bool cmp_write_bin8(cmp_ctx_t *ctx, const void *data, uint8_t size) {
1135   if (!cmp_write_bin8_marker(ctx, size))
1136     return false;
1137 
1138   if (size == 0)
1139     return true;
1140 
1141   if (ctx->write(ctx, data, size))
1142     return true;
1143 
1144   ctx->error = DATA_WRITING_ERROR;
1145   return false;
1146 }
1147 
cmp_write_bin16_marker(cmp_ctx_t * ctx,uint16_t size)1148 bool cmp_write_bin16_marker(cmp_ctx_t *ctx, uint16_t size) {
1149   if (!write_type_marker(ctx, BIN16_MARKER))
1150     return false;
1151 
1152   size = be16(size);
1153 
1154   if (ctx->write(ctx, &size, sizeof(uint16_t)))
1155     return true;
1156 
1157   ctx->error = LENGTH_WRITING_ERROR;
1158   return false;
1159 }
1160 
cmp_write_bin16(cmp_ctx_t * ctx,const void * data,uint16_t size)1161 bool cmp_write_bin16(cmp_ctx_t *ctx, const void *data, uint16_t size) {
1162   if (!cmp_write_bin16_marker(ctx, size))
1163     return false;
1164 
1165   if (size == 0)
1166     return true;
1167 
1168   if (ctx->write(ctx, data, size))
1169     return true;
1170 
1171   ctx->error = DATA_WRITING_ERROR;
1172   return false;
1173 }
1174 
cmp_write_bin32_marker(cmp_ctx_t * ctx,uint32_t size)1175 bool cmp_write_bin32_marker(cmp_ctx_t *ctx, uint32_t size) {
1176   if (!write_type_marker(ctx, BIN32_MARKER))
1177     return false;
1178 
1179   size = be32(size);
1180 
1181   if (ctx->write(ctx, &size, sizeof(uint32_t)))
1182     return true;
1183 
1184   ctx->error = LENGTH_WRITING_ERROR;
1185   return false;
1186 }
1187 
cmp_write_bin32(cmp_ctx_t * ctx,const void * data,uint32_t size)1188 bool cmp_write_bin32(cmp_ctx_t *ctx, const void *data, uint32_t size) {
1189   if (!cmp_write_bin32_marker(ctx, size))
1190     return false;
1191 
1192   if (size == 0)
1193     return true;
1194 
1195   if (ctx->write(ctx, data, size))
1196     return true;
1197 
1198   ctx->error = DATA_WRITING_ERROR;
1199   return false;
1200 }
1201 
cmp_write_bin_marker(cmp_ctx_t * ctx,uint32_t size)1202 bool cmp_write_bin_marker(cmp_ctx_t *ctx, uint32_t size) {
1203   if (size <= 0xFF)
1204     return cmp_write_bin8_marker(ctx, (uint8_t)size);
1205   if (size <= 0xFFFF)
1206     return cmp_write_bin16_marker(ctx, (uint16_t)size);
1207 
1208   return cmp_write_bin32_marker(ctx, size);
1209 }
1210 
cmp_write_bin(cmp_ctx_t * ctx,const void * data,uint32_t size)1211 bool cmp_write_bin(cmp_ctx_t *ctx, const void *data, uint32_t size) {
1212   if (size <= 0xFF)
1213     return cmp_write_bin8(ctx, data, (uint8_t)size);
1214   if (size <= 0xFFFF)
1215     return cmp_write_bin16(ctx, data, (uint16_t)size);
1216 
1217   return cmp_write_bin32(ctx, data, size);
1218 }
1219 
cmp_write_fixarray(cmp_ctx_t * ctx,uint8_t size)1220 bool cmp_write_fixarray(cmp_ctx_t *ctx, uint8_t size) {
1221   if (size <= FIXARRAY_SIZE)
1222     return write_fixed_value(ctx, FIXARRAY_MARKER | size);
1223 
1224   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
1225   return false;
1226 }
1227 
cmp_write_array16(cmp_ctx_t * ctx,uint16_t size)1228 bool cmp_write_array16(cmp_ctx_t *ctx, uint16_t size) {
1229   if (!write_type_marker(ctx, ARRAY16_MARKER))
1230     return false;
1231 
1232   size = be16(size);
1233 
1234   if (ctx->write(ctx, &size, sizeof(uint16_t)))
1235     return true;
1236 
1237   ctx->error = LENGTH_WRITING_ERROR;
1238   return false;
1239 }
1240 
cmp_write_array32(cmp_ctx_t * ctx,uint32_t size)1241 bool cmp_write_array32(cmp_ctx_t *ctx, uint32_t size) {
1242   if (!write_type_marker(ctx, ARRAY32_MARKER))
1243     return false;
1244 
1245   size = be32(size);
1246 
1247   if (ctx->write(ctx, &size, sizeof(uint32_t)))
1248     return true;
1249 
1250   ctx->error = LENGTH_WRITING_ERROR;
1251   return false;
1252 }
1253 
cmp_write_array(cmp_ctx_t * ctx,uint32_t size)1254 bool cmp_write_array(cmp_ctx_t *ctx, uint32_t size) {
1255   if (size <= FIXARRAY_SIZE)
1256     return cmp_write_fixarray(ctx, (uint8_t)size);
1257   if (size <= 0xFFFF)
1258     return cmp_write_array16(ctx, (uint16_t)size);
1259 
1260   return cmp_write_array32(ctx, size);
1261 }
1262 
cmp_write_fixmap(cmp_ctx_t * ctx,uint8_t size)1263 bool cmp_write_fixmap(cmp_ctx_t *ctx, uint8_t size) {
1264   if (size <= FIXMAP_SIZE)
1265     return write_fixed_value(ctx, FIXMAP_MARKER | size);
1266 
1267   ctx->error = INPUT_VALUE_TOO_LARGE_ERROR;
1268   return false;
1269 }
1270 
cmp_write_map16(cmp_ctx_t * ctx,uint16_t size)1271 bool cmp_write_map16(cmp_ctx_t *ctx, uint16_t size) {
1272   if (!write_type_marker(ctx, MAP16_MARKER))
1273     return false;
1274 
1275   size = be16(size);
1276 
1277   if (ctx->write(ctx, &size, sizeof(uint16_t)))
1278     return true;
1279 
1280   ctx->error = LENGTH_WRITING_ERROR;
1281   return false;
1282 }
1283 
cmp_write_map32(cmp_ctx_t * ctx,uint32_t size)1284 bool cmp_write_map32(cmp_ctx_t *ctx, uint32_t size) {
1285   if (!write_type_marker(ctx, MAP32_MARKER))
1286     return false;
1287 
1288   size = be32(size);
1289 
1290   if (ctx->write(ctx, &size, sizeof(uint32_t)))
1291     return true;
1292 
1293   ctx->error = LENGTH_WRITING_ERROR;
1294   return false;
1295 }
1296 
cmp_write_map(cmp_ctx_t * ctx,uint32_t size)1297 bool cmp_write_map(cmp_ctx_t *ctx, uint32_t size) {
1298   if (size <= FIXMAP_SIZE)
1299     return cmp_write_fixmap(ctx, (uint8_t)size);
1300   if (size <= 0xFFFF)
1301     return cmp_write_map16(ctx, (uint16_t)size);
1302 
1303   return cmp_write_map32(ctx, size);
1304 }
1305 
cmp_write_fixext1_marker(cmp_ctx_t * ctx,int8_t type)1306 bool cmp_write_fixext1_marker(cmp_ctx_t *ctx, int8_t type) {
1307   if (!write_type_marker(ctx, FIXEXT1_MARKER))
1308     return false;
1309 
1310   if (ctx->write(ctx, &type, sizeof(int8_t)))
1311     return true;
1312 
1313   ctx->error = EXT_TYPE_WRITING_ERROR;
1314   return false;
1315 }
1316 
cmp_write_fixext1(cmp_ctx_t * ctx,int8_t type,const void * data)1317 bool cmp_write_fixext1(cmp_ctx_t *ctx, int8_t type, const void *data) {
1318   if (!cmp_write_fixext1_marker(ctx, type))
1319     return false;
1320 
1321   if (ctx->write(ctx, data, 1))
1322     return true;
1323 
1324   ctx->error = DATA_WRITING_ERROR;
1325   return false;
1326 }
1327 
cmp_write_fixext2_marker(cmp_ctx_t * ctx,int8_t type)1328 bool cmp_write_fixext2_marker(cmp_ctx_t *ctx, int8_t type) {
1329   if (!write_type_marker(ctx, FIXEXT2_MARKER))
1330     return false;
1331 
1332   if (ctx->write(ctx, &type, sizeof(int8_t)))
1333     return true;
1334 
1335   ctx->error = EXT_TYPE_WRITING_ERROR;
1336   return false;
1337 }
1338 
cmp_write_fixext2(cmp_ctx_t * ctx,int8_t type,const void * data)1339 bool cmp_write_fixext2(cmp_ctx_t *ctx, int8_t type, const void *data) {
1340   if (!cmp_write_fixext2_marker(ctx, type))
1341     return false;
1342 
1343   if (ctx->write(ctx, data, 2))
1344     return true;
1345 
1346   ctx->error = DATA_WRITING_ERROR;
1347   return false;
1348 }
1349 
cmp_write_fixext4_marker(cmp_ctx_t * ctx,int8_t type)1350 bool cmp_write_fixext4_marker(cmp_ctx_t *ctx, int8_t type) {
1351   if (!write_type_marker(ctx, FIXEXT4_MARKER))
1352     return false;
1353 
1354   if (ctx->write(ctx, &type, sizeof(int8_t)))
1355     return true;
1356 
1357   ctx->error = EXT_TYPE_WRITING_ERROR;
1358   return false;
1359 }
1360 
cmp_write_fixext4(cmp_ctx_t * ctx,int8_t type,const void * data)1361 bool cmp_write_fixext4(cmp_ctx_t *ctx, int8_t type, const void *data) {
1362   if (!cmp_write_fixext4_marker(ctx, type))
1363     return false;
1364 
1365   if (ctx->write(ctx, data, 4))
1366     return true;
1367 
1368   ctx->error = DATA_WRITING_ERROR;
1369   return false;
1370 }
1371 
cmp_write_fixext8_marker(cmp_ctx_t * ctx,int8_t type)1372 bool cmp_write_fixext8_marker(cmp_ctx_t *ctx, int8_t type) {
1373   if (!write_type_marker(ctx, FIXEXT8_MARKER))
1374     return false;
1375 
1376   if (ctx->write(ctx, &type, sizeof(int8_t)))
1377     return true;
1378 
1379   ctx->error = EXT_TYPE_WRITING_ERROR;
1380   return false;
1381 }
1382 
cmp_write_fixext8(cmp_ctx_t * ctx,int8_t type,const void * data)1383 bool cmp_write_fixext8(cmp_ctx_t *ctx, int8_t type, const void *data) {
1384   if (!cmp_write_fixext8_marker(ctx, type))
1385     return false;
1386 
1387   if (ctx->write(ctx, data, 8))
1388     return true;
1389 
1390   ctx->error = DATA_WRITING_ERROR;
1391   return false;
1392 }
1393 
cmp_write_fixext16_marker(cmp_ctx_t * ctx,int8_t type)1394 bool cmp_write_fixext16_marker(cmp_ctx_t *ctx, int8_t type) {
1395   if (!write_type_marker(ctx, FIXEXT16_MARKER))
1396     return false;
1397 
1398   if (ctx->write(ctx, &type, sizeof(int8_t)))
1399     return true;
1400 
1401   ctx->error = EXT_TYPE_WRITING_ERROR;
1402   return false;
1403 }
1404 
cmp_write_fixext16(cmp_ctx_t * ctx,int8_t type,const void * data)1405 bool cmp_write_fixext16(cmp_ctx_t *ctx, int8_t type, const void *data) {
1406   if (!cmp_write_fixext16_marker(ctx, type))
1407     return false;
1408 
1409   if (ctx->write(ctx, data, 16))
1410     return true;
1411 
1412   ctx->error = DATA_WRITING_ERROR;
1413   return false;
1414 }
1415 
cmp_write_ext8_marker(cmp_ctx_t * ctx,int8_t type,uint8_t size)1416 bool cmp_write_ext8_marker(cmp_ctx_t *ctx, int8_t type, uint8_t size) {
1417   if (!write_type_marker(ctx, EXT8_MARKER))
1418     return false;
1419 
1420   if (!ctx->write(ctx, &size, sizeof(uint8_t))) {
1421     ctx->error = LENGTH_WRITING_ERROR;
1422     return false;
1423   }
1424 
1425   if (ctx->write(ctx, &type, sizeof(int8_t)))
1426     return true;
1427 
1428   ctx->error = EXT_TYPE_WRITING_ERROR;
1429   return false;
1430 }
1431 
cmp_write_ext8(cmp_ctx_t * ctx,int8_t tp,uint8_t sz,const void * data)1432 bool cmp_write_ext8(cmp_ctx_t *ctx, int8_t tp, uint8_t sz, const void *data) {
1433   if (!cmp_write_ext8_marker(ctx, tp, sz))
1434     return false;
1435 
1436   if (ctx->write(ctx, data, sz))
1437     return true;
1438 
1439   ctx->error = DATA_WRITING_ERROR;
1440   return false;
1441 }
1442 
cmp_write_ext16_marker(cmp_ctx_t * ctx,int8_t type,uint16_t size)1443 bool cmp_write_ext16_marker(cmp_ctx_t *ctx, int8_t type, uint16_t size) {
1444   if (!write_type_marker(ctx, EXT16_MARKER))
1445     return false;
1446 
1447   size = be16(size);
1448 
1449   if (!ctx->write(ctx, &size, sizeof(uint16_t))) {
1450     ctx->error = LENGTH_WRITING_ERROR;
1451     return false;
1452   }
1453 
1454   if (ctx->write(ctx, &type, sizeof(int8_t)))
1455     return true;
1456 
1457   ctx->error = EXT_TYPE_WRITING_ERROR;
1458   return false;
1459 }
1460 
cmp_write_ext16(cmp_ctx_t * ctx,int8_t tp,uint16_t sz,const void * data)1461 bool cmp_write_ext16(cmp_ctx_t *ctx, int8_t tp, uint16_t sz, const void *data) {
1462   if (!cmp_write_ext16_marker(ctx, tp, sz))
1463     return false;
1464 
1465   if (ctx->write(ctx, data, sz))
1466     return true;
1467 
1468   ctx->error = DATA_WRITING_ERROR;
1469   return false;
1470 }
1471 
cmp_write_ext32_marker(cmp_ctx_t * ctx,int8_t type,uint32_t size)1472 bool cmp_write_ext32_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size) {
1473   if (!write_type_marker(ctx, EXT32_MARKER))
1474     return false;
1475 
1476   size = be32(size);
1477 
1478   if (!ctx->write(ctx, &size, sizeof(uint32_t))) {
1479     ctx->error = LENGTH_WRITING_ERROR;
1480     return false;
1481   }
1482 
1483   if (ctx->write(ctx, &type, sizeof(int8_t)))
1484     return true;
1485 
1486   ctx->error = EXT_TYPE_WRITING_ERROR;
1487   return false;
1488 }
1489 
cmp_write_ext32(cmp_ctx_t * ctx,int8_t tp,uint32_t sz,const void * data)1490 bool cmp_write_ext32(cmp_ctx_t *ctx, int8_t tp, uint32_t sz, const void *data) {
1491   if (!cmp_write_ext32_marker(ctx, tp, sz))
1492     return false;
1493 
1494   if (ctx->write(ctx, data, sz))
1495     return true;
1496 
1497   ctx->error = DATA_WRITING_ERROR;
1498   return false;
1499 }
1500 
cmp_write_ext_marker(cmp_ctx_t * ctx,int8_t tp,uint32_t sz)1501 bool cmp_write_ext_marker(cmp_ctx_t *ctx, int8_t tp, uint32_t sz) {
1502   if (sz == 1)
1503     return cmp_write_fixext1_marker(ctx, tp);
1504   if (sz == 2)
1505     return cmp_write_fixext2_marker(ctx, tp);
1506   if (sz == 4)
1507     return cmp_write_fixext4_marker(ctx, tp);
1508   if (sz == 8)
1509     return cmp_write_fixext8_marker(ctx, tp);
1510   if (sz == 16)
1511     return cmp_write_fixext16_marker(ctx, tp);
1512   if (sz <= 0xFF)
1513     return cmp_write_ext8_marker(ctx, tp, (uint8_t)sz);
1514   if (sz <= 0xFFFF)
1515     return cmp_write_ext16_marker(ctx, tp, (uint16_t)sz);
1516 
1517   return cmp_write_ext32_marker(ctx, tp, sz);
1518 }
1519 
cmp_write_ext(cmp_ctx_t * ctx,int8_t tp,uint32_t sz,const void * data)1520 bool cmp_write_ext(cmp_ctx_t *ctx, int8_t tp, uint32_t sz, const void *data) {
1521   if (sz == 1)
1522     return cmp_write_fixext1(ctx, tp, data);
1523   if (sz == 2)
1524     return cmp_write_fixext2(ctx, tp, data);
1525   if (sz == 4)
1526     return cmp_write_fixext4(ctx, tp, data);
1527   if (sz == 8)
1528     return cmp_write_fixext8(ctx, tp, data);
1529   if (sz == 16)
1530     return cmp_write_fixext16(ctx, tp, data);
1531   if (sz <= 0xFF)
1532     return cmp_write_ext8(ctx, tp, (uint8_t)sz, data);
1533   if (sz <= 0xFFFF)
1534     return cmp_write_ext16(ctx, tp, (uint16_t)sz, data);
1535 
1536   return cmp_write_ext32(ctx, tp, sz, data);
1537 }
1538 
cmp_write_object(cmp_ctx_t * ctx,cmp_object_t * obj)1539 bool cmp_write_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
1540   switch(obj->type) {
1541     case CMP_TYPE_POSITIVE_FIXNUM:
1542       return cmp_write_pfix(ctx, obj->as.u8);
1543     case CMP_TYPE_FIXMAP:
1544       return cmp_write_fixmap(ctx, (uint8_t)obj->as.map_size);
1545     case CMP_TYPE_FIXARRAY:
1546       return cmp_write_fixarray(ctx, (uint8_t)obj->as.array_size);
1547     case CMP_TYPE_FIXSTR:
1548       return cmp_write_fixstr_marker(ctx, (uint8_t)obj->as.str_size);
1549     case CMP_TYPE_NIL:
1550       return cmp_write_nil(ctx);
1551     case CMP_TYPE_BOOLEAN:
1552       if (obj->as.boolean)
1553         return cmp_write_true(ctx);
1554       return cmp_write_false(ctx);
1555     case CMP_TYPE_BIN8:
1556       return cmp_write_bin8_marker(ctx, (uint8_t)obj->as.bin_size);
1557     case CMP_TYPE_BIN16:
1558       return cmp_write_bin16_marker(ctx, (uint16_t)obj->as.bin_size);
1559     case CMP_TYPE_BIN32:
1560       return cmp_write_bin32_marker(ctx, obj->as.bin_size);
1561     case CMP_TYPE_EXT8:
1562       return cmp_write_ext8_marker(
1563         ctx, obj->as.ext.type, (uint8_t)obj->as.ext.size
1564       );
1565     case CMP_TYPE_EXT16:
1566       return cmp_write_ext16_marker(
1567         ctx, obj->as.ext.type, (uint16_t)obj->as.ext.size
1568       );
1569     case CMP_TYPE_EXT32:
1570       return cmp_write_ext32_marker(ctx, obj->as.ext.type, obj->as.ext.size);
1571     case CMP_TYPE_FLOAT:
1572       return cmp_write_float(ctx, obj->as.flt);
1573     case CMP_TYPE_DOUBLE:
1574       return cmp_write_double(ctx, obj->as.dbl);
1575     case CMP_TYPE_UINT8:
1576       return cmp_write_u8(ctx, obj->as.u8);
1577     case CMP_TYPE_UINT16:
1578       return cmp_write_u16(ctx, obj->as.u16);
1579     case CMP_TYPE_UINT32:
1580       return cmp_write_u32(ctx, obj->as.u32);
1581     case CMP_TYPE_UINT64:
1582       return cmp_write_u64(ctx, obj->as.u64);
1583     case CMP_TYPE_SINT8:
1584       return cmp_write_s8(ctx, obj->as.s8);
1585     case CMP_TYPE_SINT16:
1586       return cmp_write_s16(ctx, obj->as.s16);
1587     case CMP_TYPE_SINT32:
1588       return cmp_write_s32(ctx, obj->as.s32);
1589     case CMP_TYPE_SINT64:
1590       return cmp_write_s64(ctx, obj->as.s64);
1591     case CMP_TYPE_FIXEXT1:
1592       return cmp_write_fixext1_marker(ctx, obj->as.ext.type);
1593     case CMP_TYPE_FIXEXT2:
1594       return cmp_write_fixext2_marker(ctx, obj->as.ext.type);
1595     case CMP_TYPE_FIXEXT4:
1596       return cmp_write_fixext4_marker(ctx, obj->as.ext.type);
1597     case CMP_TYPE_FIXEXT8:
1598       return cmp_write_fixext8_marker(ctx, obj->as.ext.type);
1599     case CMP_TYPE_FIXEXT16:
1600       return cmp_write_fixext16_marker(ctx, obj->as.ext.type);
1601     case CMP_TYPE_STR8:
1602       return cmp_write_str8_marker(ctx, (uint8_t)obj->as.str_size);
1603     case CMP_TYPE_STR16:
1604       return cmp_write_str16_marker(ctx, (uint16_t)obj->as.str_size);
1605     case CMP_TYPE_STR32:
1606       return cmp_write_str32_marker(ctx, obj->as.str_size);
1607     case CMP_TYPE_ARRAY16:
1608       return cmp_write_array16(ctx, (uint16_t)obj->as.array_size);
1609     case CMP_TYPE_ARRAY32:
1610       return cmp_write_array32(ctx, obj->as.array_size);
1611     case CMP_TYPE_MAP16:
1612       return cmp_write_map16(ctx, (uint16_t)obj->as.map_size);
1613     case CMP_TYPE_MAP32:
1614       return cmp_write_map32(ctx, obj->as.map_size);
1615     case CMP_TYPE_NEGATIVE_FIXNUM:
1616       return cmp_write_nfix(ctx, obj->as.s8);
1617     default:
1618       ctx->error = INVALID_TYPE_ERROR;
1619       return false;
1620   }
1621 }
1622 
cmp_write_object_v4(cmp_ctx_t * ctx,cmp_object_t * obj)1623 bool cmp_write_object_v4(cmp_ctx_t *ctx, cmp_object_t *obj) {
1624   switch(obj->type) {
1625     case CMP_TYPE_POSITIVE_FIXNUM:
1626       return cmp_write_pfix(ctx, obj->as.u8);
1627     case CMP_TYPE_FIXMAP:
1628       return cmp_write_fixmap(ctx, (uint8_t)obj->as.map_size);
1629     case CMP_TYPE_FIXARRAY:
1630       return cmp_write_fixarray(ctx, (uint8_t)obj->as.array_size);
1631     case CMP_TYPE_FIXSTR:
1632       return cmp_write_fixstr_marker(ctx, (uint8_t)obj->as.str_size);
1633     case CMP_TYPE_NIL:
1634       return cmp_write_nil(ctx);
1635     case CMP_TYPE_BOOLEAN:
1636       if (obj->as.boolean)
1637         return cmp_write_true(ctx);
1638       return cmp_write_false(ctx);
1639     case CMP_TYPE_EXT8:
1640       return cmp_write_ext8_marker(ctx, obj->as.ext.type, (uint8_t)obj->as.ext.size);
1641     case CMP_TYPE_EXT16:
1642       return cmp_write_ext16_marker(
1643         ctx, obj->as.ext.type, (uint16_t)obj->as.ext.size
1644       );
1645     case CMP_TYPE_EXT32:
1646       return cmp_write_ext32_marker(ctx, obj->as.ext.type, obj->as.ext.size);
1647     case CMP_TYPE_FLOAT:
1648       return cmp_write_float(ctx, obj->as.flt);
1649     case CMP_TYPE_DOUBLE:
1650       return cmp_write_double(ctx, obj->as.dbl);
1651     case CMP_TYPE_UINT8:
1652       return cmp_write_u8(ctx, obj->as.u8);
1653     case CMP_TYPE_UINT16:
1654       return cmp_write_u16(ctx, obj->as.u16);
1655     case CMP_TYPE_UINT32:
1656       return cmp_write_u32(ctx, obj->as.u32);
1657     case CMP_TYPE_UINT64:
1658       return cmp_write_u64(ctx, obj->as.u64);
1659     case CMP_TYPE_SINT8:
1660       return cmp_write_s8(ctx, obj->as.s8);
1661     case CMP_TYPE_SINT16:
1662       return cmp_write_s16(ctx, obj->as.s16);
1663     case CMP_TYPE_SINT32:
1664       return cmp_write_s32(ctx, obj->as.s32);
1665     case CMP_TYPE_SINT64:
1666       return cmp_write_s64(ctx, obj->as.s64);
1667     case CMP_TYPE_FIXEXT1:
1668       return cmp_write_fixext1_marker(ctx, obj->as.ext.type);
1669     case CMP_TYPE_FIXEXT2:
1670       return cmp_write_fixext2_marker(ctx, obj->as.ext.type);
1671     case CMP_TYPE_FIXEXT4:
1672       return cmp_write_fixext4_marker(ctx, obj->as.ext.type);
1673     case CMP_TYPE_FIXEXT8:
1674       return cmp_write_fixext8_marker(ctx, obj->as.ext.type);
1675     case CMP_TYPE_FIXEXT16:
1676       return cmp_write_fixext16_marker(ctx, obj->as.ext.type);
1677     case CMP_TYPE_STR16:
1678       return cmp_write_str16_marker(ctx, (uint16_t)obj->as.str_size);
1679     case CMP_TYPE_STR32:
1680       return cmp_write_str32_marker(ctx, obj->as.str_size);
1681     case CMP_TYPE_ARRAY16:
1682       return cmp_write_array16(ctx, (uint16_t)obj->as.array_size);
1683     case CMP_TYPE_ARRAY32:
1684       return cmp_write_array32(ctx, obj->as.array_size);
1685     case CMP_TYPE_MAP16:
1686       return cmp_write_map16(ctx, (uint16_t)obj->as.map_size);
1687     case CMP_TYPE_MAP32:
1688       return cmp_write_map32(ctx, obj->as.map_size);
1689     case CMP_TYPE_NEGATIVE_FIXNUM:
1690       return cmp_write_nfix(ctx, obj->as.s8);
1691     default:
1692       ctx->error = INVALID_TYPE_ERROR;
1693       return false;
1694   }
1695 }
1696 
cmp_read_pfix(cmp_ctx_t * ctx,uint8_t * c)1697 bool cmp_read_pfix(cmp_ctx_t *ctx, uint8_t *c) {
1698   cmp_object_t obj;
1699 
1700   if (!cmp_read_object(ctx, &obj))
1701     return false;
1702 
1703   if (obj.type != CMP_TYPE_POSITIVE_FIXNUM) {
1704     ctx->error = INVALID_TYPE_ERROR;
1705     return false;
1706   }
1707 
1708   *c = obj.as.u8;
1709   return true;
1710 }
1711 
cmp_read_nfix(cmp_ctx_t * ctx,int8_t * c)1712 bool cmp_read_nfix(cmp_ctx_t *ctx, int8_t *c) {
1713   cmp_object_t obj;
1714 
1715   if (!cmp_read_object(ctx, &obj))
1716     return false;
1717 
1718   if (obj.type != CMP_TYPE_NEGATIVE_FIXNUM) {
1719     ctx->error = INVALID_TYPE_ERROR;
1720     return false;
1721   }
1722 
1723   *c = obj.as.s8;
1724   return true;
1725 }
1726 
cmp_read_sfix(cmp_ctx_t * ctx,int8_t * c)1727 bool cmp_read_sfix(cmp_ctx_t *ctx, int8_t *c) {
1728   cmp_object_t obj;
1729 
1730   if (!cmp_read_object(ctx, &obj))
1731     return false;
1732 
1733   switch (obj.type) {
1734     case CMP_TYPE_POSITIVE_FIXNUM:
1735     case CMP_TYPE_NEGATIVE_FIXNUM:
1736       *c = obj.as.s8;
1737       return true;
1738     default:
1739       ctx->error = INVALID_TYPE_ERROR;
1740       return false;
1741   }
1742 }
1743 
cmp_read_s8(cmp_ctx_t * ctx,int8_t * c)1744 bool cmp_read_s8(cmp_ctx_t *ctx, int8_t *c) {
1745   cmp_object_t obj;
1746 
1747   if (!cmp_read_object(ctx, &obj))
1748     return false;
1749 
1750   if (obj.type != CMP_TYPE_SINT8) {
1751     ctx->error = INVALID_TYPE_ERROR;
1752     return false;
1753   }
1754 
1755   *c = obj.as.s8;
1756   return true;
1757 }
1758 
cmp_read_s16(cmp_ctx_t * ctx,int16_t * s)1759 bool cmp_read_s16(cmp_ctx_t *ctx, int16_t *s) {
1760   cmp_object_t obj;
1761 
1762   if (!cmp_read_object(ctx, &obj))
1763     return false;
1764 
1765   if (obj.type != CMP_TYPE_SINT16) {
1766     ctx->error = INVALID_TYPE_ERROR;
1767     return false;
1768   }
1769 
1770   *s = obj.as.s16;
1771   return true;
1772 }
1773 
cmp_read_s32(cmp_ctx_t * ctx,int32_t * i)1774 bool cmp_read_s32(cmp_ctx_t *ctx, int32_t *i) {
1775   cmp_object_t obj;
1776 
1777   if (!cmp_read_object(ctx, &obj))
1778     return false;
1779 
1780   if (obj.type != CMP_TYPE_SINT32) {
1781     ctx->error = INVALID_TYPE_ERROR;
1782     return false;
1783   }
1784 
1785   *i = obj.as.s32;
1786   return true;
1787 }
1788 
cmp_read_s64(cmp_ctx_t * ctx,int64_t * l)1789 bool cmp_read_s64(cmp_ctx_t *ctx, int64_t *l) {
1790   cmp_object_t obj;
1791 
1792   if (!cmp_read_object(ctx, &obj))
1793     return false;
1794 
1795   if (obj.type != CMP_TYPE_SINT64) {
1796     ctx->error = INVALID_TYPE_ERROR;
1797     return false;
1798   }
1799 
1800   *l = obj.as.s64;
1801   return true;
1802 }
1803 
cmp_read_char(cmp_ctx_t * ctx,int8_t * c)1804 bool cmp_read_char(cmp_ctx_t *ctx, int8_t *c) {
1805   cmp_object_t obj;
1806 
1807   if (!cmp_read_object(ctx, &obj))
1808     return false;
1809 
1810   switch (obj.type) {
1811     case CMP_TYPE_POSITIVE_FIXNUM:
1812     case CMP_TYPE_NEGATIVE_FIXNUM:
1813     case CMP_TYPE_SINT8:
1814       *c = obj.as.s8;
1815       return true;
1816     case CMP_TYPE_UINT8:
1817       if (obj.as.u8 <= 127) {
1818         *c = obj.as.u8;
1819         return true;
1820       }
1821       break;
1822     default:
1823       break;
1824   }
1825 
1826   ctx->error = INVALID_TYPE_ERROR;
1827   return false;
1828 }
1829 
cmp_read_short(cmp_ctx_t * ctx,int16_t * s)1830 bool cmp_read_short(cmp_ctx_t *ctx, int16_t *s) {
1831   cmp_object_t obj;
1832 
1833   if (!cmp_read_object(ctx, &obj))
1834     return false;
1835 
1836   switch (obj.type) {
1837     case CMP_TYPE_POSITIVE_FIXNUM:
1838     case CMP_TYPE_NEGATIVE_FIXNUM:
1839     case CMP_TYPE_SINT8:
1840       *s = obj.as.s8;
1841       return true;
1842     case CMP_TYPE_UINT8:
1843       *s = obj.as.u8;
1844       return true;
1845     case CMP_TYPE_SINT16:
1846       *s = obj.as.s16;
1847       return true;
1848     case CMP_TYPE_UINT16:
1849       if (obj.as.u16 <= 32767) {
1850         *s = obj.as.u16;
1851         return true;
1852       }
1853       break;
1854     default:
1855       break;
1856   }
1857 
1858   ctx->error = INVALID_TYPE_ERROR;
1859   return false;
1860 }
1861 
cmp_read_int(cmp_ctx_t * ctx,int32_t * i)1862 bool cmp_read_int(cmp_ctx_t *ctx, int32_t *i) {
1863   cmp_object_t obj;
1864 
1865   if (!cmp_read_object(ctx, &obj))
1866     return false;
1867 
1868   switch (obj.type) {
1869     case CMP_TYPE_POSITIVE_FIXNUM:
1870     case CMP_TYPE_NEGATIVE_FIXNUM:
1871     case CMP_TYPE_SINT8:
1872       *i = obj.as.s8;
1873       return true;
1874     case CMP_TYPE_UINT8:
1875       *i = obj.as.u8;
1876       return true;
1877     case CMP_TYPE_SINT16:
1878       *i = obj.as.s16;
1879       return true;
1880     case CMP_TYPE_UINT16:
1881       *i = obj.as.u16;
1882       return true;
1883     case CMP_TYPE_SINT32:
1884       *i = obj.as.s32;
1885       return true;
1886     case CMP_TYPE_UINT32:
1887       if (obj.as.u32 <= 2147483647) {
1888         *i = obj.as.u32;
1889         return true;
1890       }
1891       break;
1892     default:
1893       break;
1894   }
1895 
1896   ctx->error = INVALID_TYPE_ERROR;
1897   return false;
1898 }
1899 
cmp_read_long(cmp_ctx_t * ctx,int64_t * d)1900 bool cmp_read_long(cmp_ctx_t *ctx, int64_t *d) {
1901   cmp_object_t obj;
1902 
1903   if (!cmp_read_object(ctx, &obj))
1904     return false;
1905 
1906   switch (obj.type) {
1907     case CMP_TYPE_POSITIVE_FIXNUM:
1908     case CMP_TYPE_NEGATIVE_FIXNUM:
1909     case CMP_TYPE_SINT8:
1910       *d = obj.as.s8;
1911       return true;
1912     case CMP_TYPE_UINT8:
1913       *d = obj.as.u8;
1914       return true;
1915     case CMP_TYPE_SINT16:
1916       *d = obj.as.s16;
1917       return true;
1918     case CMP_TYPE_UINT16:
1919       *d = obj.as.u16;
1920       return true;
1921     case CMP_TYPE_SINT32:
1922       *d = obj.as.s32;
1923       return true;
1924     case CMP_TYPE_UINT32:
1925       *d = obj.as.u32;
1926       return true;
1927     case CMP_TYPE_SINT64:
1928       *d = obj.as.s64;
1929       return true;
1930     case CMP_TYPE_UINT64:
1931       if (obj.as.u64 <= 9223372036854775807) {
1932         *d = obj.as.u64;
1933         return true;
1934       }
1935       break;
1936     default:
1937       break;
1938   }
1939 
1940   ctx->error = INVALID_TYPE_ERROR;
1941   return false;
1942 }
1943 
cmp_read_integer(cmp_ctx_t * ctx,int64_t * d)1944 bool cmp_read_integer(cmp_ctx_t *ctx, int64_t *d) {
1945   return cmp_read_long(ctx, d);
1946 }
1947 
cmp_read_ufix(cmp_ctx_t * ctx,uint8_t * c)1948 bool cmp_read_ufix(cmp_ctx_t *ctx, uint8_t *c) {
1949   return cmp_read_pfix(ctx, c);
1950 }
1951 
cmp_read_u8(cmp_ctx_t * ctx,uint8_t * c)1952 bool cmp_read_u8(cmp_ctx_t *ctx, uint8_t *c) {
1953   cmp_object_t obj;
1954 
1955   if (!cmp_read_object(ctx, &obj))
1956     return false;
1957 
1958   if (obj.type != CMP_TYPE_UINT8) {
1959     ctx->error = INVALID_TYPE_ERROR;
1960     return false;
1961   }
1962 
1963   *c = obj.as.u8;
1964   return true;
1965 }
1966 
cmp_read_u16(cmp_ctx_t * ctx,uint16_t * s)1967 bool cmp_read_u16(cmp_ctx_t *ctx, uint16_t *s) {
1968   cmp_object_t obj;
1969 
1970   if (!cmp_read_object(ctx, &obj))
1971     return false;
1972 
1973   if (obj.type != CMP_TYPE_UINT16) {
1974     ctx->error = INVALID_TYPE_ERROR;
1975     return false;
1976   }
1977 
1978   *s = obj.as.u16;
1979   return true;
1980 }
1981 
cmp_read_u32(cmp_ctx_t * ctx,uint32_t * i)1982 bool cmp_read_u32(cmp_ctx_t *ctx, uint32_t *i) {
1983   cmp_object_t obj;
1984 
1985   if (!cmp_read_object(ctx, &obj))
1986     return false;
1987 
1988   if (obj.type != CMP_TYPE_UINT32) {
1989     ctx->error = INVALID_TYPE_ERROR;
1990     return false;
1991   }
1992 
1993   *i = obj.as.u32;
1994   return true;
1995 }
1996 
cmp_read_u64(cmp_ctx_t * ctx,uint64_t * l)1997 bool cmp_read_u64(cmp_ctx_t *ctx, uint64_t *l) {
1998   cmp_object_t obj;
1999 
2000   if (!cmp_read_object(ctx, &obj))
2001     return false;
2002 
2003   if (obj.type != CMP_TYPE_UINT64) {
2004     ctx->error = INVALID_TYPE_ERROR;
2005     return false;
2006   }
2007 
2008   *l = obj.as.u64;
2009   return true;
2010 }
2011 
cmp_read_uchar(cmp_ctx_t * ctx,uint8_t * c)2012 bool cmp_read_uchar(cmp_ctx_t *ctx, uint8_t *c) {
2013   cmp_object_t obj;
2014 
2015   if (!cmp_read_object(ctx, &obj))
2016     return false;
2017 
2018   switch (obj.type) {
2019     case CMP_TYPE_POSITIVE_FIXNUM:
2020     case CMP_TYPE_UINT8:
2021       *c = obj.as.u8;
2022       return true;
2023     case CMP_TYPE_NEGATIVE_FIXNUM:
2024     case CMP_TYPE_SINT8:
2025       if (obj.as.s8 >= 0) {
2026         *c = obj.as.s8;
2027         return true;
2028       }
2029       break;
2030     default:
2031       break;
2032   }
2033 
2034   ctx->error = INVALID_TYPE_ERROR;
2035   return false;
2036 }
2037 
cmp_read_ushort(cmp_ctx_t * ctx,uint16_t * s)2038 bool cmp_read_ushort(cmp_ctx_t *ctx, uint16_t *s) {
2039   cmp_object_t obj;
2040 
2041   if (!cmp_read_object(ctx, &obj))
2042     return false;
2043 
2044   switch (obj.type) {
2045     case CMP_TYPE_POSITIVE_FIXNUM:
2046     case CMP_TYPE_UINT8:
2047       *s = obj.as.u8;
2048       return true;
2049     case CMP_TYPE_UINT16:
2050       *s = obj.as.u16;
2051       return true;
2052     case CMP_TYPE_NEGATIVE_FIXNUM:
2053     case CMP_TYPE_SINT8:
2054       if (obj.as.s8 >= 0) {
2055         *s = obj.as.s8;
2056         return true;
2057       }
2058       break;
2059     case CMP_TYPE_SINT16:
2060       if (obj.as.s16 >= 0) {
2061         *s = obj.as.s16;
2062         return true;
2063       }
2064       break;
2065     default:
2066       break;
2067   }
2068 
2069   ctx->error = INVALID_TYPE_ERROR;
2070   return false;
2071 }
2072 
cmp_read_uint(cmp_ctx_t * ctx,uint32_t * i)2073 bool cmp_read_uint(cmp_ctx_t *ctx, uint32_t *i) {
2074   cmp_object_t obj;
2075 
2076   if (!cmp_read_object(ctx, &obj))
2077     return false;
2078 
2079   switch (obj.type) {
2080     case CMP_TYPE_POSITIVE_FIXNUM:
2081     case CMP_TYPE_UINT8:
2082       *i = obj.as.u8;
2083       return true;
2084     case CMP_TYPE_UINT16:
2085       *i = obj.as.u16;
2086       return true;
2087     case CMP_TYPE_UINT32:
2088       *i = obj.as.u32;
2089       return true;
2090     case CMP_TYPE_NEGATIVE_FIXNUM:
2091     case CMP_TYPE_SINT8:
2092       if (obj.as.s8 >= 0) {
2093         *i = obj.as.s8;
2094         return true;
2095       }
2096       break;
2097     case CMP_TYPE_SINT16:
2098       if (obj.as.s16 >= 0) {
2099         *i = obj.as.s16;
2100         return true;
2101       }
2102       break;
2103     case CMP_TYPE_SINT32:
2104       if (obj.as.s32 >= 0) {
2105         *i = obj.as.s32;
2106         return true;
2107       }
2108       break;
2109     default:
2110       break;
2111   }
2112 
2113   ctx->error = INVALID_TYPE_ERROR;
2114   return false;
2115 }
2116 
cmp_read_ulong(cmp_ctx_t * ctx,uint64_t * u)2117 bool cmp_read_ulong(cmp_ctx_t *ctx, uint64_t *u) {
2118   cmp_object_t obj;
2119 
2120   if (!cmp_read_object(ctx, &obj))
2121     return false;
2122 
2123   switch (obj.type) {
2124     case CMP_TYPE_POSITIVE_FIXNUM:
2125     case CMP_TYPE_UINT8:
2126       *u = obj.as.u8;
2127       return true;
2128     case CMP_TYPE_UINT16:
2129       *u = obj.as.u16;
2130       return true;
2131     case CMP_TYPE_UINT32:
2132       *u = obj.as.u32;
2133       return true;
2134     case CMP_TYPE_UINT64:
2135       *u = obj.as.u64;
2136       return true;
2137     case CMP_TYPE_NEGATIVE_FIXNUM:
2138     case CMP_TYPE_SINT8:
2139       if (obj.as.s8 >= 0) {
2140         *u = obj.as.s8;
2141         return true;
2142       }
2143       break;
2144     case CMP_TYPE_SINT16:
2145       if (obj.as.s16 >= 0) {
2146         *u = obj.as.s16;
2147         return true;
2148       }
2149       break;
2150     case CMP_TYPE_SINT32:
2151       if (obj.as.s32 >= 0) {
2152         *u = obj.as.s32;
2153         return true;
2154       }
2155       break;
2156     case CMP_TYPE_SINT64:
2157       if (obj.as.s64 >= 0) {
2158         *u = obj.as.s64;
2159         return true;
2160       }
2161       break;
2162     default:
2163       break;
2164   }
2165 
2166   ctx->error = INVALID_TYPE_ERROR;
2167   return false;
2168 }
2169 
cmp_read_uinteger(cmp_ctx_t * ctx,uint64_t * d)2170 bool cmp_read_uinteger(cmp_ctx_t *ctx, uint64_t *d) {
2171   return cmp_read_ulong(ctx, d);
2172 }
2173 
cmp_read_float(cmp_ctx_t * ctx,float * f)2174 bool cmp_read_float(cmp_ctx_t *ctx, float *f) {
2175   cmp_object_t obj;
2176 
2177   if (!cmp_read_object(ctx, &obj))
2178     return false;
2179 
2180   if (obj.type != CMP_TYPE_FLOAT) {
2181     ctx->error = INVALID_TYPE_ERROR;
2182     return false;
2183   }
2184 
2185   *f = obj.as.flt;
2186 
2187   return true;
2188 }
2189 
cmp_read_double(cmp_ctx_t * ctx,double * d)2190 bool cmp_read_double(cmp_ctx_t *ctx, double *d) {
2191   cmp_object_t obj;
2192 
2193   if (!cmp_read_object(ctx, &obj))
2194     return false;
2195 
2196   if (obj.type != CMP_TYPE_DOUBLE) {
2197     ctx->error = INVALID_TYPE_ERROR;
2198     return false;
2199   }
2200 
2201   *d = obj.as.dbl;
2202 
2203   return true;
2204 }
2205 
cmp_read_decimal(cmp_ctx_t * ctx,double * d)2206 bool cmp_read_decimal(cmp_ctx_t *ctx, double *d) {
2207   cmp_object_t obj;
2208 
2209   if (!cmp_read_object(ctx, &obj))
2210     return false;
2211 
2212   switch (obj.type) {
2213     case CMP_TYPE_FLOAT:
2214       *d = (double)obj.as.flt;
2215       return true;
2216     case CMP_TYPE_DOUBLE:
2217       *d = obj.as.dbl;
2218       return true;
2219     default:
2220       ctx->error = INVALID_TYPE_ERROR;
2221       return false;
2222   }
2223 }
2224 
cmp_read_nil(cmp_ctx_t * ctx)2225 bool cmp_read_nil(cmp_ctx_t *ctx) {
2226   cmp_object_t obj;
2227 
2228   if (!cmp_read_object(ctx, &obj))
2229     return false;
2230 
2231   if (obj.type == CMP_TYPE_NIL)
2232     return true;
2233 
2234   ctx->error = INVALID_TYPE_ERROR;
2235   return false;
2236 }
2237 
cmp_read_bool(cmp_ctx_t * ctx,bool * b)2238 bool cmp_read_bool(cmp_ctx_t *ctx, bool *b) {
2239   cmp_object_t obj;
2240 
2241   if (!cmp_read_object(ctx, &obj))
2242     return false;
2243 
2244   if (obj.type != CMP_TYPE_BOOLEAN) {
2245     ctx->error = INVALID_TYPE_ERROR;
2246     return false;
2247   }
2248 
2249   if (obj.as.boolean)
2250     *b = true;
2251   else
2252     *b = false;
2253 
2254   return true;
2255 }
2256 
cmp_read_bool_as_u8(cmp_ctx_t * ctx,uint8_t * b)2257 bool cmp_read_bool_as_u8(cmp_ctx_t *ctx, uint8_t *b) {
2258   cmp_object_t obj;
2259 
2260   if (!cmp_read_object(ctx, &obj))
2261     return false;
2262 
2263   if (obj.type != CMP_TYPE_BOOLEAN) {
2264     ctx->error = INVALID_TYPE_ERROR;
2265     return false;
2266   }
2267 
2268   if (obj.as.boolean)
2269     *b = 1;
2270   else
2271     *b = 0;
2272 
2273   return true;
2274 }
2275 
cmp_read_str_size(cmp_ctx_t * ctx,uint32_t * size)2276 bool cmp_read_str_size(cmp_ctx_t *ctx, uint32_t *size) {
2277   cmp_object_t obj;
2278 
2279   if (!cmp_read_object(ctx, &obj))
2280     return false;
2281 
2282   switch (obj.type) {
2283     case CMP_TYPE_FIXSTR:
2284     case CMP_TYPE_STR8:
2285     case CMP_TYPE_STR16:
2286     case CMP_TYPE_STR32:
2287       *size = obj.as.str_size;
2288       return true;
2289     default:
2290       ctx->error = INVALID_TYPE_ERROR;
2291       return false;
2292   }
2293 }
2294 
cmp_read_str(cmp_ctx_t * ctx,char * data,uint32_t * size)2295 bool cmp_read_str(cmp_ctx_t *ctx, char *data, uint32_t *size) {
2296   uint32_t str_size = 0;
2297 
2298   if (!cmp_read_str_size(ctx, &str_size))
2299     return false;
2300 
2301   if ((str_size + 1) > *size) {
2302     *size = str_size;
2303     ctx->error = STR_DATA_LENGTH_TOO_LONG_ERROR;
2304     return false;
2305   }
2306 
2307   if (!ctx->read(ctx, data, str_size)) {
2308     ctx->error = DATA_READING_ERROR;
2309     return false;
2310   }
2311 
2312   data[str_size] = 0;
2313 
2314   *size = str_size;
2315   return true;
2316 }
2317 
cmp_read_bin_size(cmp_ctx_t * ctx,uint32_t * size)2318 bool cmp_read_bin_size(cmp_ctx_t *ctx, uint32_t *size) {
2319   cmp_object_t obj;
2320 
2321   if (!cmp_read_object(ctx, &obj))
2322     return false;
2323 
2324   switch (obj.type) {
2325     case CMP_TYPE_BIN8:
2326     case CMP_TYPE_BIN16:
2327     case CMP_TYPE_BIN32:
2328       *size = obj.as.bin_size;
2329       return true;
2330     default:
2331       ctx->error = INVALID_TYPE_ERROR;
2332       return false;
2333   }
2334 }
2335 
cmp_read_bin(cmp_ctx_t * ctx,void * data,uint32_t * size)2336 bool cmp_read_bin(cmp_ctx_t *ctx, void *data, uint32_t *size) {
2337   uint32_t bin_size = 0;
2338 
2339   if (!cmp_read_bin_size(ctx, &bin_size))
2340     return false;
2341 
2342   if (bin_size > *size) {
2343     ctx->error = BIN_DATA_LENGTH_TOO_LONG_ERROR;
2344     return false;
2345   }
2346 
2347   if (!ctx->read(ctx, data, bin_size)) {
2348     ctx->error = DATA_READING_ERROR;
2349     return false;
2350   }
2351 
2352   *size = bin_size;
2353   return true;
2354 }
2355 
cmp_read_array(cmp_ctx_t * ctx,uint32_t * size)2356 bool cmp_read_array(cmp_ctx_t *ctx, uint32_t *size) {
2357   cmp_object_t obj;
2358 
2359   if (!cmp_read_object(ctx, &obj))
2360     return false;
2361 
2362   switch (obj.type) {
2363     case CMP_TYPE_FIXARRAY:
2364     case CMP_TYPE_ARRAY16:
2365     case CMP_TYPE_ARRAY32:
2366       *size = obj.as.array_size;
2367       return true;
2368     default:
2369       ctx->error = INVALID_TYPE_ERROR;
2370       return false;
2371   }
2372 }
2373 
cmp_read_map(cmp_ctx_t * ctx,uint32_t * size)2374 bool cmp_read_map(cmp_ctx_t *ctx, uint32_t *size) {
2375   cmp_object_t obj;
2376 
2377   if (!cmp_read_object(ctx, &obj))
2378     return false;
2379 
2380   switch (obj.type) {
2381     case CMP_TYPE_FIXMAP:
2382     case CMP_TYPE_MAP16:
2383     case CMP_TYPE_MAP32:
2384       *size = obj.as.map_size;
2385       return true;
2386     default:
2387       ctx->error = INVALID_TYPE_ERROR;
2388       return false;
2389   }
2390 }
2391 
cmp_read_fixext1_marker(cmp_ctx_t * ctx,int8_t * type)2392 bool cmp_read_fixext1_marker(cmp_ctx_t *ctx, int8_t *type) {
2393   cmp_object_t obj;
2394 
2395   if (!cmp_read_object(ctx, &obj))
2396     return false;
2397 
2398   if (obj.type != CMP_TYPE_FIXEXT1) {
2399     ctx->error = INVALID_TYPE_ERROR;
2400     return false;
2401   }
2402 
2403   *type = obj.as.ext.type;
2404   return true;
2405 }
2406 
cmp_read_fixext1(cmp_ctx_t * ctx,int8_t * type,void * data)2407 bool cmp_read_fixext1(cmp_ctx_t *ctx, int8_t *type, void *data) {
2408   if (!cmp_read_fixext1_marker(ctx, type))
2409     return false;
2410 
2411   if (ctx->read(ctx, data, 1))
2412     return true;
2413 
2414   ctx->error = DATA_READING_ERROR;
2415   return false;
2416 }
2417 
cmp_read_fixext2_marker(cmp_ctx_t * ctx,int8_t * type)2418 bool cmp_read_fixext2_marker(cmp_ctx_t *ctx, int8_t *type) {
2419   cmp_object_t obj;
2420 
2421   if (!cmp_read_object(ctx, &obj))
2422     return false;
2423 
2424   if (obj.type != CMP_TYPE_FIXEXT2) {
2425     ctx->error = INVALID_TYPE_ERROR;
2426     return false;
2427   }
2428 
2429   *type = obj.as.ext.type;
2430   return true;
2431 }
2432 
cmp_read_fixext2(cmp_ctx_t * ctx,int8_t * type,void * data)2433 bool cmp_read_fixext2(cmp_ctx_t *ctx, int8_t *type, void *data) {
2434   if (!cmp_read_fixext2_marker(ctx, type))
2435     return false;
2436 
2437   if (ctx->read(ctx, data, 2))
2438     return true;
2439 
2440   ctx->error = DATA_READING_ERROR;
2441   return false;
2442 }
2443 
cmp_read_fixext4_marker(cmp_ctx_t * ctx,int8_t * type)2444 bool cmp_read_fixext4_marker(cmp_ctx_t *ctx, int8_t *type) {
2445   cmp_object_t obj;
2446 
2447   if (!cmp_read_object(ctx, &obj))
2448     return false;
2449 
2450   if (obj.type != CMP_TYPE_FIXEXT4) {
2451     ctx->error = INVALID_TYPE_ERROR;
2452     return false;
2453   }
2454 
2455   *type = obj.as.ext.type;
2456   return true;
2457 }
2458 
cmp_read_fixext4(cmp_ctx_t * ctx,int8_t * type,void * data)2459 bool cmp_read_fixext4(cmp_ctx_t *ctx, int8_t *type, void *data) {
2460   if (!cmp_read_fixext4_marker(ctx, type))
2461     return false;
2462 
2463   if (ctx->read(ctx, data, 4))
2464     return true;
2465 
2466   ctx->error = DATA_READING_ERROR;
2467   return false;
2468 }
2469 
cmp_read_fixext8_marker(cmp_ctx_t * ctx,int8_t * type)2470 bool cmp_read_fixext8_marker(cmp_ctx_t *ctx, int8_t *type) {
2471   cmp_object_t obj;
2472 
2473   if (!cmp_read_object(ctx, &obj))
2474     return false;
2475 
2476   if (obj.type != CMP_TYPE_FIXEXT8) {
2477     ctx->error = INVALID_TYPE_ERROR;
2478     return false;
2479   }
2480 
2481   *type = obj.as.ext.type;
2482   return true;
2483 }
2484 
cmp_read_fixext8(cmp_ctx_t * ctx,int8_t * type,void * data)2485 bool cmp_read_fixext8(cmp_ctx_t *ctx, int8_t *type, void *data) {
2486   if (!cmp_read_fixext8_marker(ctx, type))
2487     return false;
2488 
2489   if (ctx->read(ctx, data, 8))
2490     return true;
2491 
2492   ctx->error = DATA_READING_ERROR;
2493   return false;
2494 }
2495 
cmp_read_fixext16_marker(cmp_ctx_t * ctx,int8_t * type)2496 bool cmp_read_fixext16_marker(cmp_ctx_t *ctx, int8_t *type) {
2497   cmp_object_t obj;
2498 
2499   if (!cmp_read_object(ctx, &obj))
2500     return false;
2501 
2502   if (obj.type != CMP_TYPE_FIXEXT16) {
2503     ctx->error = INVALID_TYPE_ERROR;
2504     return false;
2505   }
2506 
2507   *type = obj.as.ext.type;
2508   return true;
2509 }
2510 
cmp_read_fixext16(cmp_ctx_t * ctx,int8_t * type,void * data)2511 bool cmp_read_fixext16(cmp_ctx_t *ctx, int8_t *type, void *data) {
2512   if (!cmp_read_fixext16_marker(ctx, type))
2513     return false;
2514 
2515   if (ctx->read(ctx, data, 16))
2516     return true;
2517 
2518   ctx->error = DATA_READING_ERROR;
2519   return false;
2520 }
2521 
cmp_read_ext8_marker(cmp_ctx_t * ctx,int8_t * type,uint8_t * size)2522 bool cmp_read_ext8_marker(cmp_ctx_t *ctx, int8_t *type, uint8_t *size) {
2523   cmp_object_t obj;
2524 
2525   if (!cmp_read_object(ctx, &obj))
2526     return false;
2527 
2528   if (obj.type != CMP_TYPE_EXT8) {
2529     ctx->error = INVALID_TYPE_ERROR;
2530     return false;
2531   }
2532 
2533   *type = obj.as.ext.type;
2534   *size = (uint8_t)obj.as.ext.size;
2535 
2536   return true;
2537 }
2538 
cmp_read_ext8(cmp_ctx_t * ctx,int8_t * type,uint8_t * size,void * data)2539 bool cmp_read_ext8(cmp_ctx_t *ctx, int8_t *type, uint8_t *size, void *data) {
2540   if (!cmp_read_ext8_marker(ctx, type, size))
2541     return false;
2542 
2543   if (ctx->read(ctx, data, *size))
2544     return true;
2545 
2546   ctx->error = DATA_READING_ERROR;
2547   return false;
2548 }
2549 
cmp_read_ext16_marker(cmp_ctx_t * ctx,int8_t * type,uint16_t * size)2550 bool cmp_read_ext16_marker(cmp_ctx_t *ctx, int8_t *type, uint16_t *size) {
2551   cmp_object_t obj;
2552 
2553   if (!cmp_read_object(ctx, &obj))
2554     return false;
2555 
2556   if (obj.type != CMP_TYPE_EXT16) {
2557     ctx->error = INVALID_TYPE_ERROR;
2558     return false;
2559   }
2560 
2561   *type = obj.as.ext.type;
2562   *size = (uint16_t)obj.as.ext.size;
2563 
2564   return true;
2565 }
2566 
cmp_read_ext16(cmp_ctx_t * ctx,int8_t * type,uint16_t * size,void * data)2567 bool cmp_read_ext16(cmp_ctx_t *ctx, int8_t *type, uint16_t *size, void *data) {
2568   if (!cmp_read_ext16_marker(ctx, type, size))
2569     return false;
2570 
2571   if (ctx->read(ctx, data, *size))
2572     return true;
2573 
2574   ctx->error = DATA_READING_ERROR;
2575   return false;
2576 }
2577 
cmp_read_ext32_marker(cmp_ctx_t * ctx,int8_t * type,uint32_t * size)2578 bool cmp_read_ext32_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size) {
2579   cmp_object_t obj;
2580 
2581   if (!cmp_read_object(ctx, &obj))
2582     return false;
2583 
2584   if (obj.type != CMP_TYPE_EXT32) {
2585     ctx->error = INVALID_TYPE_ERROR;
2586     return false;
2587   }
2588 
2589   *type = obj.as.ext.type;
2590   *size = obj.as.ext.size;
2591 
2592   return true;
2593 }
2594 
cmp_read_ext32(cmp_ctx_t * ctx,int8_t * type,uint32_t * size,void * data)2595 bool cmp_read_ext32(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data) {
2596   if (!cmp_read_ext32_marker(ctx, type, size))
2597     return false;
2598 
2599   if (ctx->read(ctx, data, *size))
2600     return true;
2601 
2602   ctx->error = DATA_READING_ERROR;
2603   return false;
2604 }
2605 
cmp_read_ext_marker(cmp_ctx_t * ctx,int8_t * type,uint32_t * size)2606 bool cmp_read_ext_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size) {
2607   cmp_object_t obj;
2608 
2609   if (!cmp_read_object(ctx, &obj))
2610     return false;
2611 
2612   switch (obj.type) {
2613     case CMP_TYPE_FIXEXT1:
2614     case CMP_TYPE_FIXEXT2:
2615     case CMP_TYPE_FIXEXT4:
2616     case CMP_TYPE_FIXEXT8:
2617     case CMP_TYPE_FIXEXT16:
2618     case CMP_TYPE_EXT8:
2619     case CMP_TYPE_EXT16:
2620     case CMP_TYPE_EXT32:
2621       *type = obj.as.ext.type;
2622       *size = obj.as.ext.size;
2623       return true;
2624     default:
2625       ctx->error = INVALID_TYPE_ERROR;
2626       return false;
2627   }
2628 }
2629 
cmp_read_ext(cmp_ctx_t * ctx,int8_t * type,uint32_t * size,void * data)2630 bool cmp_read_ext(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data) {
2631   if (!cmp_read_ext_marker(ctx, type, size))
2632     return false;
2633 
2634   if (ctx->read(ctx, data, *size))
2635     return true;
2636 
2637   ctx->error = DATA_READING_ERROR;
2638   return false;
2639 }
2640 
cmp_read_object(cmp_ctx_t * ctx,cmp_object_t * obj)2641 bool cmp_read_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
2642   uint8_t type_marker = 0;
2643 
2644   if (!read_type_marker(ctx, &type_marker))
2645     return false;
2646 
2647   if (!type_marker_to_cmp_type(type_marker, &obj->type)) {
2648     ctx->error = INVALID_TYPE_ERROR;
2649     return false;
2650   }
2651 
2652   return read_obj_data(ctx, type_marker, obj);
2653 }
2654 
cmp_skip_object(cmp_ctx_t * ctx,cmp_object_t * obj)2655 bool cmp_skip_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
2656   return cmp_skip_object_limit(ctx, obj, 0);
2657 }
2658 
cmp_skip_object_limit(cmp_ctx_t * ctx,cmp_object_t * obj,uint32_t limit)2659 bool cmp_skip_object_limit(cmp_ctx_t *ctx, cmp_object_t *obj, uint32_t limit) {
2660   size_t element_count = 1;
2661   uint32_t depth = 0;
2662 
2663   while (element_count) {
2664     uint8_t type_marker = 0;
2665     uint8_t cmp_type;
2666     uint32_t size = 0;
2667 
2668     if (!read_type_marker(ctx, &type_marker)) {
2669       return false;
2670     }
2671 
2672     if (!type_marker_to_cmp_type(type_marker, &cmp_type)) {
2673       ctx->error = INVALID_TYPE_ERROR;
2674       return false;
2675     }
2676 
2677     switch (cmp_type) {
2678       case CMP_TYPE_FIXARRAY:
2679       case CMP_TYPE_ARRAY16:
2680       case CMP_TYPE_ARRAY32:
2681       case CMP_TYPE_FIXMAP:
2682       case CMP_TYPE_MAP16:
2683       case CMP_TYPE_MAP32:
2684         depth++;
2685 
2686         if (depth > limit) {
2687           obj->type = cmp_type;
2688 
2689           if (!read_obj_data(ctx, type_marker, obj)) {
2690             return false;
2691           }
2692 
2693           ctx->error = SKIP_DEPTH_LIMIT_EXCEEDED_ERROR;
2694 
2695           return false;
2696         }
2697 
2698         break;
2699       default:
2700         if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
2701           return false;
2702         }
2703 
2704         if (size) {
2705           switch (cmp_type) {
2706             case CMP_TYPE_FIXEXT1:
2707             case CMP_TYPE_FIXEXT2:
2708             case CMP_TYPE_FIXEXT4:
2709             case CMP_TYPE_FIXEXT8:
2710             case CMP_TYPE_FIXEXT16:
2711             case CMP_TYPE_EXT8:
2712             case CMP_TYPE_EXT16:
2713             case CMP_TYPE_EXT32:
2714               size++;
2715             default:
2716               break;
2717           }
2718 
2719           skip_bytes(ctx, size);
2720         }
2721     }
2722 
2723     element_count--;
2724 
2725     switch (cmp_type) {
2726       case CMP_TYPE_FIXARRAY:
2727       case CMP_TYPE_ARRAY16:
2728       case CMP_TYPE_ARRAY32:
2729         if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
2730           return false;
2731         }
2732         element_count += size;
2733         break;
2734       case CMP_TYPE_FIXMAP:
2735       case CMP_TYPE_MAP16:
2736       case CMP_TYPE_MAP32:
2737         if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
2738           return false;
2739         }
2740         element_count += ((size_t)size) * 2;
2741         break;
2742       default:
2743         break;
2744     }
2745   }
2746 
2747   return true;
2748 }
2749 
cmp_skip_object_no_limit(cmp_ctx_t * ctx)2750 bool cmp_skip_object_no_limit(cmp_ctx_t *ctx) {
2751   size_t element_count = 1;
2752 
2753   while (element_count) {
2754     uint8_t type_marker = 0;
2755     uint8_t cmp_type = 0;
2756     uint32_t size = 0;
2757 
2758     if (!read_type_marker(ctx, &type_marker)) {
2759       return false;
2760     }
2761 
2762     if (!type_marker_to_cmp_type(type_marker, &cmp_type)) {
2763       ctx->error = INVALID_TYPE_ERROR;
2764       return false;
2765     }
2766 
2767     switch (cmp_type) {
2768       case CMP_TYPE_FIXARRAY:
2769       case CMP_TYPE_ARRAY16:
2770       case CMP_TYPE_ARRAY32:
2771       case CMP_TYPE_FIXMAP:
2772       case CMP_TYPE_MAP16:
2773       case CMP_TYPE_MAP32:
2774         break;
2775       default:
2776         if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
2777           return false;
2778         }
2779 
2780         if (size) {
2781           switch (cmp_type) {
2782             case CMP_TYPE_FIXEXT1:
2783             case CMP_TYPE_FIXEXT2:
2784             case CMP_TYPE_FIXEXT4:
2785             case CMP_TYPE_FIXEXT8:
2786             case CMP_TYPE_FIXEXT16:
2787             case CMP_TYPE_EXT8:
2788             case CMP_TYPE_EXT16:
2789             case CMP_TYPE_EXT32:
2790               size++;
2791             default:
2792               break;
2793           }
2794 
2795           skip_bytes(ctx, size);
2796         }
2797     }
2798 
2799     element_count--;
2800 
2801     switch (cmp_type) {
2802       case CMP_TYPE_FIXARRAY:
2803       case CMP_TYPE_ARRAY16:
2804       case CMP_TYPE_ARRAY32:
2805         if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
2806           return false;
2807         }
2808         element_count += size;
2809         break;
2810       case CMP_TYPE_FIXMAP:
2811       case CMP_TYPE_MAP16:
2812       case CMP_TYPE_MAP32:
2813         if (!read_type_size(ctx, type_marker, cmp_type, &size)) {
2814           return false;
2815         }
2816         element_count += ((size_t)size) * 2;
2817         break;
2818       default:
2819         break;
2820     }
2821   }
2822 
2823   return true;
2824 }
2825 
cmp_object_is_char(cmp_object_t * obj)2826 bool cmp_object_is_char(cmp_object_t *obj) {
2827   switch (obj->type) {
2828     case CMP_TYPE_NEGATIVE_FIXNUM:
2829     case CMP_TYPE_SINT8:
2830       return true;
2831     default:
2832       return false;
2833   }
2834 }
2835 
cmp_object_is_short(cmp_object_t * obj)2836 bool cmp_object_is_short(cmp_object_t *obj) {
2837   switch (obj->type) {
2838     case CMP_TYPE_NEGATIVE_FIXNUM:
2839     case CMP_TYPE_SINT8:
2840     case CMP_TYPE_SINT16:
2841       return true;
2842     default:
2843       return false;
2844   }
2845 }
2846 
cmp_object_is_int(cmp_object_t * obj)2847 bool cmp_object_is_int(cmp_object_t *obj) {
2848   switch (obj->type) {
2849     case CMP_TYPE_NEGATIVE_FIXNUM:
2850     case CMP_TYPE_SINT8:
2851     case CMP_TYPE_SINT16:
2852     case CMP_TYPE_SINT32:
2853       return true;
2854     default:
2855       return false;
2856   }
2857 }
2858 
cmp_object_is_long(cmp_object_t * obj)2859 bool cmp_object_is_long(cmp_object_t *obj) {
2860   switch (obj->type) {
2861     case CMP_TYPE_NEGATIVE_FIXNUM:
2862     case CMP_TYPE_SINT8:
2863     case CMP_TYPE_SINT16:
2864     case CMP_TYPE_SINT32:
2865     case CMP_TYPE_SINT64:
2866       return true;
2867     default:
2868       return false;
2869   }
2870 }
2871 
cmp_object_is_sinteger(cmp_object_t * obj)2872 bool cmp_object_is_sinteger(cmp_object_t *obj) {
2873   return cmp_object_is_long(obj);
2874 }
2875 
cmp_object_is_uchar(cmp_object_t * obj)2876 bool cmp_object_is_uchar(cmp_object_t *obj) {
2877   switch (obj->type) {
2878     case CMP_TYPE_POSITIVE_FIXNUM:
2879     case CMP_TYPE_UINT8:
2880       return true;
2881     default:
2882       return false;
2883   }
2884 }
2885 
cmp_object_is_ushort(cmp_object_t * obj)2886 bool cmp_object_is_ushort(cmp_object_t *obj) {
2887   switch (obj->type) {
2888     case CMP_TYPE_POSITIVE_FIXNUM:
2889     case CMP_TYPE_UINT8:
2890       return true;
2891     case CMP_TYPE_UINT16:
2892       return true;
2893     default:
2894       return false;
2895   }
2896 }
2897 
cmp_object_is_uint(cmp_object_t * obj)2898 bool cmp_object_is_uint(cmp_object_t *obj) {
2899   switch (obj->type) {
2900     case CMP_TYPE_POSITIVE_FIXNUM:
2901     case CMP_TYPE_UINT8:
2902     case CMP_TYPE_UINT16:
2903     case CMP_TYPE_UINT32:
2904       return true;
2905     default:
2906       return false;
2907   }
2908 }
2909 
cmp_object_is_ulong(cmp_object_t * obj)2910 bool cmp_object_is_ulong(cmp_object_t *obj) {
2911   switch (obj->type) {
2912     case CMP_TYPE_POSITIVE_FIXNUM:
2913     case CMP_TYPE_UINT8:
2914     case CMP_TYPE_UINT16:
2915     case CMP_TYPE_UINT32:
2916     case CMP_TYPE_UINT64:
2917       return true;
2918     default:
2919       return false;
2920   }
2921 }
2922 
cmp_object_is_uinteger(cmp_object_t * obj)2923 bool cmp_object_is_uinteger(cmp_object_t *obj) {
2924   return cmp_object_is_ulong(obj);
2925 }
2926 
cmp_object_is_float(cmp_object_t * obj)2927 bool cmp_object_is_float(cmp_object_t *obj) {
2928   if (obj->type == CMP_TYPE_FLOAT)
2929     return true;
2930 
2931   return false;
2932 }
2933 
cmp_object_is_double(cmp_object_t * obj)2934 bool cmp_object_is_double(cmp_object_t *obj) {
2935   if (obj->type == CMP_TYPE_DOUBLE)
2936     return true;
2937 
2938   return false;
2939 }
2940 
cmp_object_is_nil(cmp_object_t * obj)2941 bool cmp_object_is_nil(cmp_object_t *obj) {
2942   if (obj->type == CMP_TYPE_NIL)
2943     return true;
2944 
2945   return false;
2946 }
2947 
cmp_object_is_bool(cmp_object_t * obj)2948 bool cmp_object_is_bool(cmp_object_t *obj) {
2949   if (obj->type == CMP_TYPE_BOOLEAN)
2950     return true;
2951 
2952   return false;
2953 }
2954 
cmp_object_is_str(cmp_object_t * obj)2955 bool cmp_object_is_str(cmp_object_t *obj) {
2956   switch (obj->type) {
2957     case CMP_TYPE_FIXSTR:
2958     case CMP_TYPE_STR8:
2959     case CMP_TYPE_STR16:
2960     case CMP_TYPE_STR32:
2961       return true;
2962     default:
2963       return false;
2964   }
2965 }
2966 
cmp_object_is_bin(cmp_object_t * obj)2967 bool cmp_object_is_bin(cmp_object_t *obj) {
2968   switch (obj->type) {
2969     case CMP_TYPE_BIN8:
2970     case CMP_TYPE_BIN16:
2971     case CMP_TYPE_BIN32:
2972       return true;
2973     default:
2974       return false;
2975   }
2976 }
2977 
cmp_object_is_array(cmp_object_t * obj)2978 bool cmp_object_is_array(cmp_object_t *obj) {
2979   switch (obj->type) {
2980     case CMP_TYPE_FIXARRAY:
2981     case CMP_TYPE_ARRAY16:
2982     case CMP_TYPE_ARRAY32:
2983       return true;
2984     default:
2985       return false;
2986   }
2987 }
2988 
cmp_object_is_map(cmp_object_t * obj)2989 bool cmp_object_is_map(cmp_object_t *obj) {
2990   switch (obj->type) {
2991     case CMP_TYPE_FIXMAP:
2992     case CMP_TYPE_MAP16:
2993     case CMP_TYPE_MAP32:
2994       return true;
2995     default:
2996       return false;
2997   }
2998 }
2999 
cmp_object_is_ext(cmp_object_t * obj)3000 bool cmp_object_is_ext(cmp_object_t *obj) {
3001   switch (obj->type) {
3002     case CMP_TYPE_FIXEXT1:
3003     case CMP_TYPE_FIXEXT2:
3004     case CMP_TYPE_FIXEXT4:
3005     case CMP_TYPE_FIXEXT8:
3006     case CMP_TYPE_FIXEXT16:
3007     case CMP_TYPE_EXT8:
3008     case CMP_TYPE_EXT16:
3009     case CMP_TYPE_EXT32:
3010       return true;
3011     default:
3012       return false;
3013   }
3014 }
3015 
cmp_object_as_char(cmp_object_t * obj,int8_t * c)3016 bool cmp_object_as_char(cmp_object_t *obj, int8_t *c) {
3017   switch (obj->type) {
3018     case CMP_TYPE_POSITIVE_FIXNUM:
3019     case CMP_TYPE_NEGATIVE_FIXNUM:
3020     case CMP_TYPE_SINT8:
3021       *c = obj->as.s8;
3022       return true;
3023     case CMP_TYPE_UINT8:
3024       if (obj->as.u8 <= 127) {
3025         *c = obj->as.s8;
3026         return true;
3027       }
3028       else {
3029         return false;
3030       }
3031     default:
3032         return false;
3033   }
3034 }
3035 
cmp_object_as_short(cmp_object_t * obj,int16_t * s)3036 bool cmp_object_as_short(cmp_object_t *obj, int16_t *s) {
3037   switch (obj->type) {
3038     case CMP_TYPE_POSITIVE_FIXNUM:
3039     case CMP_TYPE_NEGATIVE_FIXNUM:
3040     case CMP_TYPE_SINT8:
3041       *s = obj->as.s8;
3042       return true;
3043     case CMP_TYPE_UINT8:
3044       *s = obj->as.u8;
3045       return true;
3046     case CMP_TYPE_SINT16:
3047       *s = obj->as.s16;
3048       return true;
3049     case CMP_TYPE_UINT16:
3050       if (obj->as.u16 <= 32767) {
3051         *s = obj->as.u16;
3052         return true;
3053       }
3054       else {
3055         return false;
3056       }
3057     default:
3058         return false;
3059   }
3060 }
3061 
cmp_object_as_int(cmp_object_t * obj,int32_t * i)3062 bool cmp_object_as_int(cmp_object_t *obj, int32_t *i) {
3063   switch (obj->type) {
3064     case CMP_TYPE_POSITIVE_FIXNUM:
3065     case CMP_TYPE_NEGATIVE_FIXNUM:
3066     case CMP_TYPE_SINT8:
3067       *i = obj->as.s8;
3068       return true;
3069     case CMP_TYPE_UINT8:
3070       *i = obj->as.u8;
3071       return true;
3072     case CMP_TYPE_SINT16:
3073       *i = obj->as.s16;
3074       return true;
3075     case CMP_TYPE_UINT16:
3076       *i = obj->as.u16;
3077       return true;
3078     case CMP_TYPE_SINT32:
3079       *i = obj->as.s32;
3080       return true;
3081     case CMP_TYPE_UINT32:
3082       if (obj->as.u32 <= 2147483647) {
3083         *i = obj->as.u32;
3084         return true;
3085       }
3086       else {
3087         return false;
3088       }
3089     default:
3090         return false;
3091   }
3092 }
3093 
cmp_object_as_long(cmp_object_t * obj,int64_t * d)3094 bool cmp_object_as_long(cmp_object_t *obj, int64_t *d) {
3095   switch (obj->type) {
3096     case CMP_TYPE_POSITIVE_FIXNUM:
3097     case CMP_TYPE_NEGATIVE_FIXNUM:
3098     case CMP_TYPE_SINT8:
3099       *d = obj->as.s8;
3100       return true;
3101     case CMP_TYPE_UINT8:
3102       *d = obj->as.u8;
3103       return true;
3104     case CMP_TYPE_SINT16:
3105       *d = obj->as.s16;
3106       return true;
3107     case CMP_TYPE_UINT16:
3108       *d = obj->as.u16;
3109       return true;
3110     case CMP_TYPE_SINT32:
3111       *d = obj->as.s32;
3112       return true;
3113     case CMP_TYPE_UINT32:
3114       *d = obj->as.u32;
3115       return true;
3116     case CMP_TYPE_SINT64:
3117       *d = obj->as.s64;
3118       return true;
3119     case CMP_TYPE_UINT64:
3120       if (obj->as.u64 <= 9223372036854775807) {
3121         *d = obj->as.u64;
3122         return true;
3123       }
3124       else {
3125         return false;
3126       }
3127     default:
3128         return false;
3129   }
3130 }
3131 
cmp_object_as_sinteger(cmp_object_t * obj,int64_t * d)3132 bool cmp_object_as_sinteger(cmp_object_t *obj, int64_t *d) {
3133   return cmp_object_as_long(obj, d);
3134 }
3135 
cmp_object_as_uchar(cmp_object_t * obj,uint8_t * c)3136 bool cmp_object_as_uchar(cmp_object_t *obj, uint8_t *c) {
3137   switch (obj->type) {
3138     case CMP_TYPE_POSITIVE_FIXNUM:
3139     case CMP_TYPE_UINT8:
3140       *c = obj->as.u8;
3141       return true;
3142     default:
3143         return false;
3144   }
3145 }
3146 
cmp_object_as_ushort(cmp_object_t * obj,uint16_t * s)3147 bool cmp_object_as_ushort(cmp_object_t *obj, uint16_t *s) {
3148   switch (obj->type) {
3149     case CMP_TYPE_POSITIVE_FIXNUM:
3150     case CMP_TYPE_UINT8:
3151       *s = obj->as.u8;
3152       return true;
3153     case CMP_TYPE_UINT16:
3154       *s = obj->as.u16;
3155       return true;
3156     default:
3157         return false;
3158   }
3159 }
3160 
cmp_object_as_uint(cmp_object_t * obj,uint32_t * i)3161 bool cmp_object_as_uint(cmp_object_t *obj, uint32_t *i) {
3162   switch (obj->type) {
3163     case CMP_TYPE_POSITIVE_FIXNUM:
3164     case CMP_TYPE_UINT8:
3165       *i = obj->as.u8;
3166       return true;
3167     case CMP_TYPE_UINT16:
3168       *i = obj->as.u16;
3169       return true;
3170     case CMP_TYPE_UINT32:
3171       *i = obj->as.u32;
3172       return true;
3173     default:
3174         return false;
3175   }
3176 }
3177 
cmp_object_as_ulong(cmp_object_t * obj,uint64_t * u)3178 bool cmp_object_as_ulong(cmp_object_t *obj, uint64_t *u) {
3179   switch (obj->type) {
3180     case CMP_TYPE_POSITIVE_FIXNUM:
3181     case CMP_TYPE_UINT8:
3182       *u = obj->as.u8;
3183       return true;
3184     case CMP_TYPE_UINT16:
3185       *u = obj->as.u16;
3186       return true;
3187     case CMP_TYPE_UINT32:
3188       *u = obj->as.u32;
3189       return true;
3190     case CMP_TYPE_UINT64:
3191       *u = obj->as.u64;
3192       return true;
3193     default:
3194         return false;
3195   }
3196 }
3197 
cmp_object_as_uinteger(cmp_object_t * obj,uint64_t * d)3198 bool cmp_object_as_uinteger(cmp_object_t *obj, uint64_t *d) {
3199   return cmp_object_as_ulong(obj, d);
3200 }
3201 
cmp_object_as_float(cmp_object_t * obj,float * f)3202 bool cmp_object_as_float(cmp_object_t *obj, float *f) {
3203   if (obj->type == CMP_TYPE_FLOAT) {
3204     *f = obj->as.flt;
3205     return true;
3206   }
3207 
3208   return false;
3209 }
3210 
cmp_object_as_double(cmp_object_t * obj,double * d)3211 bool cmp_object_as_double(cmp_object_t *obj, double *d) {
3212   if (obj->type == CMP_TYPE_DOUBLE) {
3213     *d = obj->as.dbl;
3214     return true;
3215   }
3216 
3217   return false;
3218 }
3219 
cmp_object_as_bool(cmp_object_t * obj,bool * b)3220 bool cmp_object_as_bool(cmp_object_t *obj, bool *b) {
3221   if (obj->type == CMP_TYPE_BOOLEAN) {
3222     if (obj->as.boolean)
3223       *b = true;
3224     else
3225       *b = false;
3226 
3227     return true;
3228   }
3229 
3230   return false;
3231 }
3232 
cmp_object_as_str(cmp_object_t * obj,uint32_t * size)3233 bool cmp_object_as_str(cmp_object_t *obj, uint32_t *size) {
3234   switch (obj->type) {
3235     case CMP_TYPE_FIXSTR:
3236     case CMP_TYPE_STR8:
3237     case CMP_TYPE_STR16:
3238     case CMP_TYPE_STR32:
3239       *size = obj->as.str_size;
3240       return true;
3241     default:
3242         return false;
3243   }
3244 }
3245 
cmp_object_as_bin(cmp_object_t * obj,uint32_t * size)3246 bool cmp_object_as_bin(cmp_object_t *obj, uint32_t *size) {
3247   switch (obj->type) {
3248     case CMP_TYPE_BIN8:
3249     case CMP_TYPE_BIN16:
3250     case CMP_TYPE_BIN32:
3251       *size = obj->as.bin_size;
3252       return true;
3253     default:
3254         return false;
3255   }
3256 }
3257 
cmp_object_as_array(cmp_object_t * obj,uint32_t * size)3258 bool cmp_object_as_array(cmp_object_t *obj, uint32_t *size) {
3259   switch (obj->type) {
3260     case CMP_TYPE_FIXARRAY:
3261     case CMP_TYPE_ARRAY16:
3262     case CMP_TYPE_ARRAY32:
3263       *size = obj->as.array_size;
3264       return true;
3265     default:
3266         return false;
3267   }
3268 }
3269 
cmp_object_as_map(cmp_object_t * obj,uint32_t * size)3270 bool cmp_object_as_map(cmp_object_t *obj, uint32_t *size) {
3271   switch (obj->type) {
3272     case CMP_TYPE_FIXMAP:
3273     case CMP_TYPE_MAP16:
3274     case CMP_TYPE_MAP32:
3275       *size = obj->as.map_size;
3276       return true;
3277     default:
3278         return false;
3279   }
3280 }
3281 
cmp_object_as_ext(cmp_object_t * obj,int8_t * type,uint32_t * size)3282 bool cmp_object_as_ext(cmp_object_t *obj, int8_t *type, uint32_t *size) {
3283   switch (obj->type) {
3284     case CMP_TYPE_FIXEXT1:
3285     case CMP_TYPE_FIXEXT2:
3286     case CMP_TYPE_FIXEXT4:
3287     case CMP_TYPE_FIXEXT8:
3288     case CMP_TYPE_FIXEXT16:
3289     case CMP_TYPE_EXT8:
3290     case CMP_TYPE_EXT16:
3291     case CMP_TYPE_EXT32:
3292       *type = obj->as.ext.type;
3293       *size = obj->as.ext.size;
3294       return true;
3295     default:
3296         return false;
3297   }
3298 }
3299 
cmp_object_to_str(cmp_ctx_t * ctx,cmp_object_t * obj,char * data,uint32_t buf_size)3300 bool cmp_object_to_str(cmp_ctx_t *ctx, cmp_object_t *obj, char *data,
3301                                                           uint32_t buf_size) {
3302   uint32_t str_size = 0;
3303 
3304   switch (obj->type) {
3305     case CMP_TYPE_FIXSTR:
3306     case CMP_TYPE_STR8:
3307     case CMP_TYPE_STR16:
3308     case CMP_TYPE_STR32:
3309       str_size = obj->as.str_size;
3310       if ((str_size + 1) > buf_size) {
3311         ctx->error = STR_DATA_LENGTH_TOO_LONG_ERROR;
3312         return false;
3313       }
3314 
3315       if (!ctx->read(ctx, data, str_size)) {
3316         ctx->error = DATA_READING_ERROR;
3317         return false;
3318       }
3319 
3320       data[str_size] = 0;
3321       return true;
3322     default:
3323       return false;
3324   }
3325 }
3326 
cmp_object_to_bin(cmp_ctx_t * ctx,cmp_object_t * obj,void * data,uint32_t buf_size)3327 bool cmp_object_to_bin(cmp_ctx_t *ctx, cmp_object_t *obj, void *data,
3328                                                           uint32_t buf_size) {
3329   uint32_t bin_size = 0;
3330 
3331   switch (obj->type) {
3332     case CMP_TYPE_BIN8:
3333     case CMP_TYPE_BIN16:
3334     case CMP_TYPE_BIN32:
3335       bin_size = obj->as.bin_size;
3336       if (bin_size > buf_size) {
3337         ctx->error = BIN_DATA_LENGTH_TOO_LONG_ERROR;
3338         return false;
3339       }
3340 
3341       if (!ctx->read(ctx, data, bin_size)) {
3342         ctx->error = DATA_READING_ERROR;
3343         return false;
3344       }
3345       return true;
3346     default:
3347       return false;
3348   }
3349 }
3350 
3351 /* vi: set et ts=2 sw=2: */
3352 
3353