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