Coverage Report

Created: 2025-10-08 19:34

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