Coverage Report

Created: 2024-01-26 01:52

/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_t {
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
17.2k
static bool is_bigendian(void) {
110
#ifdef WORDS_BIGENDIAN
111
  return WORDS_BIGENDIAN;
112
#else
113
17.2k
  const int32_t i_ = 1;
114
17.2k
  const char *i_bytes = (const char *)&i_;
115
17.2k
  return *i_bytes == 0;
116
17.2k
#endif /* WORDS_BIGENDIAN */
117
17.2k
}
118
119
12.2k
static uint16_t be16(uint16_t x) {
120
12.2k
  if (!is_bigendian())
121
12.2k
    return ((x >> 8) & 0x00ff)
122
12.2k
         | ((x << 8) & 0xff00);
123
124
0
  return x;
125
12.2k
}
126
127
302
static int16_t sbe16(int16_t x) {
128
302
  return (int16_t)be16((uint16_t)x);
129
302
}
130
131
4.80k
static uint32_t be32(uint32_t x) {
132
4.80k
  if (!is_bigendian())
133
4.80k
    return ((uint32_t)be16((uint16_t)(x & 0xffff)) << 16) | (uint32_t)be16((uint16_t)(x >> 16));
134
135
0
  return x;
136
4.80k
}
137
138
115
static int32_t sbe32(int32_t x) {
139
115
  return (int32_t)be32((uint32_t)x);
140
115
}
141
142
162
static uint64_t be64(uint64_t x) {
143
162
  if (!is_bigendian())
144
162
    return ((uint64_t)be32((uint32_t)(x & 0xffffffff)) << 32) | (uint64_t)be32((uint32_t)(x >> 32));
145
146
0
  return x;
147
162
}
148
149
67
static int64_t sbe64(int64_t x) {
150
67
  return (int64_t)be64((uint64_t)x);
151
67
}
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
134k
static bool read_byte(cmp_ctx_t *ctx, uint8_t *x) {
204
134k
  return ctx->read(ctx, x, sizeof(uint8_t));
205
134k
}
206
207
288k
static bool write_byte(cmp_ctx_t *ctx, uint8_t x) {
208
288k
  return ctx->write(ctx, &x, sizeof(uint8_t)) == sizeof(uint8_t);
209
288k
}
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
134k
static bool read_type_marker(cmp_ctx_t *ctx, uint8_t *marker) {
229
134k
  if (read_byte(ctx, marker)) {
230
133k
    return true;
231
133k
  }
232
233
1.58k
  ctx->error = CMP_ERROR_TYPE_MARKER_READING;
234
1.58k
  return false;
235
134k
}
236
237
11.2k
static bool write_type_marker(cmp_ctx_t *ctx, uint8_t marker) {
238
11.2k
  if (write_byte(ctx, marker))
239
11.2k
    return true;
240
241
0
  ctx->error = CMP_ERROR_TYPE_MARKER_WRITING;
242
0
  return false;
243
11.2k
}
244
245
277k
static bool write_fixed_value(cmp_ctx_t *ctx, uint8_t value) {
246
277k
  if (write_byte(ctx, value))
247
277k
    return true;
248
249
0
  ctx->error = CMP_ERROR_FIXED_VALUE_WRITING;
250
0
  return false;
251
277k
}
252
253
133k
static bool type_marker_to_cmp_type(uint8_t type_marker, uint8_t *cmp_type) {
254
133k
  if (type_marker <= 0x7F) {
255
53.5k
    *cmp_type = CMP_TYPE_POSITIVE_FIXNUM;
256
53.5k
    return true;
257
53.5k
  }
258
259
79.7k
  if (type_marker <= 0x8F) {
260
171
    *cmp_type = CMP_TYPE_FIXMAP;
261
171
    return true;
262
171
  }
263
264
79.5k
  if (type_marker <= 0x9F) {
265
44.7k
    *cmp_type = CMP_TYPE_FIXARRAY;
266
44.7k
    return true;
267
44.7k
  }
268
269
34.8k
  if (type_marker <= 0xBF) {
270
301
    *cmp_type = CMP_TYPE_FIXSTR;
271
301
    return true;
272
301
  }
273
274
34.5k
  if (type_marker >= 0xE0) {
275
1.53k
    *cmp_type = CMP_TYPE_NEGATIVE_FIXNUM;
276
1.53k
    return true;
277
1.53k
  }
278
279
32.9k
  switch (type_marker) {
280
156
    case NIL_MARKER: {
281
156
      *cmp_type = CMP_TYPE_NIL;
282
156
      return true;
283
0
    }
284
7.42k
    case FALSE_MARKER: {
285
7.42k
      *cmp_type = CMP_TYPE_BOOLEAN;
286
7.42k
      return true;
287
0
    }
288
3.43k
    case TRUE_MARKER: {
289
3.43k
      *cmp_type = CMP_TYPE_BOOLEAN;
290
3.43k
      return true;
291
0
    }
292
5.22k
    case BIN8_MARKER: {
293
5.22k
      *cmp_type = CMP_TYPE_BIN8;
294
5.22k
      return true;
295
0
    }
296
486
    case BIN16_MARKER: {
297
486
      *cmp_type = CMP_TYPE_BIN16;
298
486
      return true;
299
0
    }
300
1.65k
    case BIN32_MARKER: {
301
1.65k
      *cmp_type = CMP_TYPE_BIN32;
302
1.65k
      return true;
303
0
    }
304
47
    case EXT8_MARKER: {
305
47
      *cmp_type = CMP_TYPE_EXT8;
306
47
      return true;
307
0
    }
308
136
    case EXT16_MARKER: {
309
136
      *cmp_type = CMP_TYPE_EXT16;
310
136
      return true;
311
0
    }
312
1.66k
    case EXT32_MARKER: {
313
1.66k
      *cmp_type = CMP_TYPE_EXT32;
314
1.66k
      return true;
315
0
    }
316
89
    case FLOAT_MARKER: {
317
89
      *cmp_type = CMP_TYPE_FLOAT;
318
89
      return true;
319
0
    }
320
69
    case DOUBLE_MARKER: {
321
69
      *cmp_type = CMP_TYPE_DOUBLE;
322
69
      return true;
323
0
    }
324
2.53k
    case U8_MARKER: {
325
2.53k
      *cmp_type = CMP_TYPE_UINT8;
326
2.53k
      return true;
327
0
    }
328
711
    case U16_MARKER: {
329
711
      *cmp_type = CMP_TYPE_UINT16;
330
711
      return true;
331
0
    }
332
3.84k
    case U32_MARKER: {
333
3.84k
      *cmp_type = CMP_TYPE_UINT32;
334
3.84k
      return true;
335
0
    }
336
146
    case U64_MARKER: {
337
146
      *cmp_type = CMP_TYPE_UINT64;
338
146
      return true;
339
0
    }
340
2.80k
    case S8_MARKER: {
341
2.80k
      *cmp_type = CMP_TYPE_SINT8;
342
2.80k
      return true;
343
0
    }
344
324
    case S16_MARKER: {
345
324
      *cmp_type = CMP_TYPE_SINT16;
346
324
      return true;
347
0
    }
348
126
    case S32_MARKER: {
349
126
      *cmp_type = CMP_TYPE_SINT32;
350
126
      return true;
351
0
    }
352
181
    case S64_MARKER: {
353
181
      *cmp_type = CMP_TYPE_SINT64;
354
181
      return true;
355
0
    }
356
94
    case FIXEXT1_MARKER: {
357
94
      *cmp_type = CMP_TYPE_FIXEXT1;
358
94
      return true;
359
0
    }
360
82
    case FIXEXT2_MARKER: {
361
82
      *cmp_type = CMP_TYPE_FIXEXT2;
362
82
      return true;
363
0
    }
364
94
    case FIXEXT4_MARKER: {
365
94
      *cmp_type = CMP_TYPE_FIXEXT4;
366
94
      return true;
367
0
    }
368
79
    case FIXEXT8_MARKER: {
369
79
      *cmp_type = CMP_TYPE_FIXEXT8;
370
79
      return true;
371
0
    }
372
84
    case FIXEXT16_MARKER: {
373
84
      *cmp_type = CMP_TYPE_FIXEXT16;
374
84
      return true;
375
0
    }
376
643
    case STR8_MARKER: {
377
643
      *cmp_type = CMP_TYPE_STR8;
378
643
      return true;
379
0
    }
380
78
    case STR16_MARKER: {
381
78
      *cmp_type = CMP_TYPE_STR16;
382
78
      return true;
383
0
    }
384
102
    case STR32_MARKER: {
385
102
      *cmp_type = CMP_TYPE_STR32;
386
102
      return true;
387
0
    }
388
275
    case ARRAY16_MARKER: {
389
275
      *cmp_type = CMP_TYPE_ARRAY16;
390
275
      return true;
391
0
    }
392
124
    case ARRAY32_MARKER: {
393
124
      *cmp_type = CMP_TYPE_ARRAY32;
394
124
      return true;
395
0
    }
396
91
    case MAP16_MARKER: {
397
91
      *cmp_type = CMP_TYPE_MAP16;
398
91
      return true;
399
0
    }
400
87
    case MAP32_MARKER: {
401
87
      *cmp_type = CMP_TYPE_MAP32;
402
87
      return true;
403
0
    }
404
75
    default: {
405
75
      return false;
406
0
    }
407
32.9k
  }
408
32.9k
}
409
410
static bool read_type_size(cmp_ctx_t *ctx, uint8_t type_marker,
411
                                           uint8_t cmp_type,
412
55.8k
                                           uint32_t *size) {
413
55.8k
  uint8_t u8temp = 0;
414
55.8k
  uint16_t u16temp = 0;
415
55.8k
  uint32_t u32temp = 0;
416
417
55.8k
  switch (cmp_type) {
418
0
    case CMP_TYPE_POSITIVE_FIXNUM: {
419
0
      *size = 0;
420
0
      return true;
421
0
    }
422
171
    case CMP_TYPE_FIXMAP: {
423
171
      *size = type_marker & FIXMAP_SIZE;
424
171
      return true;
425
0
    }
426
44.7k
    case CMP_TYPE_FIXARRAY: {
427
44.7k
      *size = type_marker & FIXARRAY_SIZE;
428
44.7k
      return true;
429
0
    }
430
301
    case CMP_TYPE_FIXSTR: {
431
301
      *size = type_marker & FIXSTR_SIZE;
432
301
      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.22k
    case CMP_TYPE_BIN8: {
443
5.22k
      if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
444
117
        ctx->error = CMP_ERROR_LENGTH_READING;
445
117
        return false;
446
117
      }
447
5.10k
      *size = u8temp;
448
5.10k
      return true;
449
5.22k
    }
450
486
    case CMP_TYPE_BIN16: {
451
486
      if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
452
25
        ctx->error = CMP_ERROR_LENGTH_READING;
453
25
        return false;
454
25
      }
455
461
      *size = be16(u16temp);
456
461
      return true;
457
486
    }
458
1.65k
    case CMP_TYPE_BIN32: {
459
1.65k
      if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
460
262
        ctx->error = CMP_ERROR_LENGTH_READING;
461
262
        return false;
462
262
      }
463
1.39k
      *size = be32(u32temp);
464
1.39k
      return true;
465
1.65k
    }
466
47
    case CMP_TYPE_EXT8: {
467
47
      if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
468
11
        ctx->error = CMP_ERROR_LENGTH_READING;
469
11
        return false;
470
11
      }
471
36
      *size = u8temp;
472
36
      return true;
473
47
    }
474
136
    case CMP_TYPE_EXT16: {
475
136
      if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
476
41
        ctx->error = CMP_ERROR_LENGTH_READING;
477
41
        return false;
478
41
      }
479
95
      *size = be16(u16temp);
480
95
      return true;
481
136
    }
482
1.66k
    case CMP_TYPE_EXT32: {
483
1.66k
      if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
484
1.56k
        ctx->error = CMP_ERROR_LENGTH_READING;
485
1.56k
        return false;
486
1.56k
      }
487
102
      *size = be32(u32temp);
488
102
      return true;
489
1.66k
    }
490
0
    case CMP_TYPE_FLOAT: {
491
0
      *size = 4;
492
0
      return true;
493
1.66k
    }
494
0
    case CMP_TYPE_DOUBLE: {
495
0
      *size = 8;
496
0
      return true;
497
1.66k
    }
498
0
    case CMP_TYPE_UINT8: {
499
0
      *size = 1;
500
0
      return true;
501
1.66k
    }
502
0
    case CMP_TYPE_UINT16: {
503
0
      *size = 2;
504
0
      return true;
505
1.66k
    }
506
0
    case CMP_TYPE_UINT32: {
507
0
      *size = 4;
508
0
      return true;
509
1.66k
    }
510
0
    case CMP_TYPE_UINT64: {
511
0
      *size = 8;
512
0
      return true;
513
1.66k
    }
514
0
    case CMP_TYPE_SINT8: {
515
0
      *size = 1;
516
0
      return true;
517
1.66k
    }
518
0
    case CMP_TYPE_SINT16: {
519
0
      *size = 2;
520
0
      return true;
521
1.66k
    }
522
0
    case CMP_TYPE_SINT32: {
523
0
      *size = 4;
524
0
      return true;
525
1.66k
    }
526
0
    case CMP_TYPE_SINT64: {
527
0
      *size = 8;
528
0
      return true;
529
1.66k
    }
530
0
    case CMP_TYPE_FIXEXT1: {
531
0
      *size = 1;
532
0
      return true;
533
1.66k
    }
534
0
    case CMP_TYPE_FIXEXT2: {
535
0
      *size = 2;
536
0
      return true;
537
1.66k
    }
538
0
    case CMP_TYPE_FIXEXT4: {
539
0
      *size = 4;
540
0
      return true;
541
1.66k
    }
542
0
    case CMP_TYPE_FIXEXT8: {
543
0
      *size = 8;
544
0
      return true;
545
1.66k
    }
546
0
    case CMP_TYPE_FIXEXT16: {
547
0
      *size = 16;
548
0
      return true;
549
1.66k
    }
550
643
    case CMP_TYPE_STR8: {
551
643
      if (!ctx->read(ctx, &u8temp, sizeof(uint8_t))) {
552
12
        ctx->error = CMP_ERROR_DATA_READING;
553
12
        return false;
554
12
      }
555
631
      *size = u8temp;
556
631
      return true;
557
643
    }
558
78
    case CMP_TYPE_STR16: {
559
78
      if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
560
11
        ctx->error = CMP_ERROR_DATA_READING;
561
11
        return false;
562
11
      }
563
67
      *size = be16(u16temp);
564
67
      return true;
565
78
    }
566
102
    case CMP_TYPE_STR32: {
567
102
      if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
568
19
        ctx->error = CMP_ERROR_DATA_READING;
569
19
        return false;
570
19
      }
571
83
      *size = be32(u32temp);
572
83
      return true;
573
102
    }
574
275
    case CMP_TYPE_ARRAY16: {
575
275
      if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
576
219
        ctx->error = CMP_ERROR_DATA_READING;
577
219
        return false;
578
219
      }
579
56
      *size = be16(u16temp);
580
56
      return true;
581
275
    }
582
124
    case CMP_TYPE_ARRAY32: {
583
124
      if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
584
37
        ctx->error = CMP_ERROR_DATA_READING;
585
37
        return false;
586
37
      }
587
87
      *size = be32(u32temp);
588
87
      return true;
589
124
    }
590
91
    case CMP_TYPE_MAP16: {
591
91
      if (!ctx->read(ctx, &u16temp, sizeof(uint16_t))) {
592
20
        ctx->error = CMP_ERROR_DATA_READING;
593
20
        return false;
594
20
      }
595
71
      *size = be16(u16temp);
596
71
      return true;
597
91
    }
598
87
    case CMP_TYPE_MAP32: {
599
87
      if (!ctx->read(ctx, &u32temp, sizeof(uint32_t))) {
600
19
        ctx->error = CMP_ERROR_DATA_READING;
601
19
        return false;
602
19
      }
603
68
      *size = be32(u32temp);
604
68
      return true;
605
87
    }
606
0
    case CMP_TYPE_NEGATIVE_FIXNUM: {
607
0
      *size = 0;
608
0
      return true;
609
87
    }
610
0
    default: {
611
0
      ctx->error = CMP_ERROR_INVALID_TYPE;
612
0
      return false;
613
87
    }
614
55.8k
  }
615
55.8k
}
616
617
static bool read_obj_data(cmp_ctx_t *ctx, uint8_t type_marker,
618
133k
                                          cmp_object_t *obj) {
619
133k
  switch (obj->type) {
620
53.5k
    case CMP_TYPE_POSITIVE_FIXNUM: {
621
53.5k
      obj->as.u8 = type_marker;
622
53.5k
      return true;
623
0
    }
624
1.53k
    case CMP_TYPE_NEGATIVE_FIXNUM: {
625
1.53k
      obj->as.s8 = (int8_t)type_marker;
626
1.53k
      return true;
627
0
    }
628
156
    case CMP_TYPE_NIL: {
629
156
      obj->as.u8 = 0;
630
156
      return true;
631
0
    }
632
10.8k
    case CMP_TYPE_BOOLEAN: {
633
10.8k
      switch (type_marker) {
634
3.43k
        case TRUE_MARKER: {
635
3.43k
          obj->as.boolean = true;
636
3.43k
          return true;
637
0
        }
638
7.42k
        case FALSE_MARKER: {
639
7.42k
          obj->as.boolean = false;
640
7.42k
          return true;
641
0
        }
642
0
        default:
643
0
          break;
644
10.8k
      }
645
0
      ctx->error = CMP_ERROR_INTERNAL;
646
0
      return false;
647
10.8k
    }
648
2.53k
    case CMP_TYPE_UINT8: {
649
2.53k
      if (!ctx->read(ctx, &obj->as.u8, sizeof(uint8_t))) {
650
12
        ctx->error = CMP_ERROR_DATA_READING;
651
12
        return false;
652
12
      }
653
2.52k
      return true;
654
2.53k
    }
655
711
    case CMP_TYPE_UINT16: {
656
711
      if (!ctx->read(ctx, &obj->as.u16, sizeof(uint16_t))) {
657
23
        ctx->error = CMP_ERROR_DATA_READING;
658
23
        return false;
659
23
      }
660
688
      obj->as.u16 = be16(obj->as.u16);
661
688
      return true;
662
711
    }
663
3.84k
    case CMP_TYPE_UINT32: {
664
3.84k
      if (!ctx->read(ctx, &obj->as.u32, sizeof(uint32_t))) {
665
1.26k
        ctx->error = CMP_ERROR_DATA_READING;
666
1.26k
        return false;
667
1.26k
      }
668
2.58k
      obj->as.u32 = be32(obj->as.u32);
669
2.58k
      return true;
670
3.84k
    }
671
146
    case CMP_TYPE_UINT64: {
672
146
      if (!ctx->read(ctx, &obj->as.u64, sizeof(uint64_t))) {
673
75
        ctx->error = CMP_ERROR_DATA_READING;
674
75
        return false;
675
75
      }
676
71
      obj->as.u64 = be64(obj->as.u64);
677
71
      return true;
678
146
    }
679
2.80k
    case CMP_TYPE_SINT8: {
680
2.80k
      if (!ctx->read(ctx, &obj->as.s8, sizeof(int8_t))) {
681
13
        ctx->error = CMP_ERROR_DATA_READING;
682
13
        return false;
683
13
      }
684
2.79k
      return true;
685
2.80k
    }
686
324
    case CMP_TYPE_SINT16: {
687
324
      if (!ctx->read(ctx, &obj->as.s16, sizeof(int16_t))) {
688
22
        ctx->error = CMP_ERROR_DATA_READING;
689
22
        return false;
690
22
      }
691
302
      obj->as.s16 = sbe16(obj->as.s16);
692
302
      return true;
693
324
    }
694
126
    case CMP_TYPE_SINT32: {
695
126
      if (!ctx->read(ctx, &obj->as.s32, sizeof(int32_t))) {
696
11
        ctx->error = CMP_ERROR_DATA_READING;
697
11
        return false;
698
11
      }
699
115
      obj->as.s32 = sbe32(obj->as.s32);
700
115
      return true;
701
126
    }
702
181
    case CMP_TYPE_SINT64: {
703
181
      if (!ctx->read(ctx, &obj->as.s64, sizeof(int64_t))) {
704
114
        ctx->error = CMP_ERROR_DATA_READING;
705
114
        return false;
706
114
      }
707
67
      obj->as.s64 = sbe64(obj->as.s64);
708
67
      return true;
709
181
    }
710
89
    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
89
      ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
722
89
      return false;
723
181
#endif /* CMP_NO_FLOAT */
724
181
    }
725
69
    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
69
      ctx->error = CMP_ERROR_DISABLED_FLOATING_POINT;
737
69
      return false;
738
181
#endif /* CMP_NO_FLOAT */
739
181
    }
740
5.22k
    case CMP_TYPE_BIN8:
741
5.71k
    case CMP_TYPE_BIN16:
742
7.36k
    case CMP_TYPE_BIN32:
743
7.36k
      return read_type_size(ctx, type_marker, obj->type, &obj->as.bin_size);
744
301
    case CMP_TYPE_FIXSTR:
745
944
    case CMP_TYPE_STR8:
746
1.02k
    case CMP_TYPE_STR16:
747
1.12k
    case CMP_TYPE_STR32:
748
1.12k
      return read_type_size(ctx, type_marker, obj->type, &obj->as.str_size);
749
44.7k
    case CMP_TYPE_FIXARRAY:
750
45.0k
    case CMP_TYPE_ARRAY16:
751
45.1k
    case CMP_TYPE_ARRAY32:
752
45.1k
      return read_type_size(ctx, type_marker, obj->type, &obj->as.array_size);
753
171
    case CMP_TYPE_FIXMAP:
754
262
    case CMP_TYPE_MAP16:
755
349
    case CMP_TYPE_MAP32:
756
349
      return read_type_size(ctx, type_marker, obj->type, &obj->as.map_size);
757
94
    case CMP_TYPE_FIXEXT1: {
758
94
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
759
26
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
760
26
        return false;
761
26
      }
762
68
      obj->as.ext.size = 1;
763
68
      return true;
764
94
    }
765
82
    case CMP_TYPE_FIXEXT2: {
766
82
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
767
12
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
768
12
        return false;
769
12
      }
770
70
      obj->as.ext.size = 2;
771
70
      return true;
772
82
    }
773
94
    case CMP_TYPE_FIXEXT4: {
774
94
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
775
11
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
776
11
        return false;
777
11
      }
778
83
      obj->as.ext.size = 4;
779
83
      return true;
780
94
    }
781
79
    case CMP_TYPE_FIXEXT8: {
782
79
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
783
11
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
784
11
        return false;
785
11
      }
786
68
      obj->as.ext.size = 8;
787
68
      return true;
788
79
    }
789
84
    case CMP_TYPE_FIXEXT16: {
790
84
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
791
35
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
792
35
        return false;
793
35
      }
794
49
      obj->as.ext.size = 16;
795
49
      return true;
796
84
    }
797
47
    case CMP_TYPE_EXT8: {
798
47
      if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
799
11
        return false;
800
11
      }
801
36
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
802
2
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
803
2
        return false;
804
2
      }
805
34
      return true;
806
36
    }
807
136
    case CMP_TYPE_EXT16: {
808
136
      if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
809
41
        return false;
810
41
      }
811
95
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
812
11
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
813
11
        return false;
814
11
      }
815
84
      return true;
816
95
    }
817
1.66k
    case CMP_TYPE_EXT32: {
818
1.66k
      if (!read_type_size(ctx, type_marker, obj->type, &obj->as.ext.size)) {
819
1.56k
        return false;
820
1.56k
      }
821
102
      if (!ctx->read(ctx, &obj->as.ext.type, sizeof(int8_t))) {
822
35
        ctx->error = CMP_ERROR_EXT_TYPE_READING;
823
35
        return false;
824
35
      }
825
67
      return true;
826
102
    }
827
0
    default:
828
0
      break;
829
133k
  }
830
831
0
  ctx->error = CMP_ERROR_INVALID_TYPE;
832
0
  return false;
833
133k
}
834
835
void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader *read,
836
                                         cmp_skipper *skip,
837
1.11M
                                         cmp_writer *write) {
838
1.11M
  ctx->error = CMP_ERROR_NONE;
839
1.11M
  ctx->buf = buf;
840
1.11M
  ctx->read = read;
841
1.11M
  ctx->skip = skip;
842
1.11M
  ctx->write = write;
843
1.11M
}
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
11.6k
bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c) {
860
11.6k
  if (c <= 0x7F)
861
11.6k
    return write_fixed_value(ctx, c);
862
863
0
  ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
864
0
  return false;
865
11.6k
}
866
867
0
bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) {
868
0
  if (c >= -32 && 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 >= -32 && 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 >= -32)
923
0
    return cmp_write_nfix(ctx, (int8_t)d);
924
0
  if (d >= -128)
925
0
    return cmp_write_s8(ctx, (int8_t)d);
926
0
  if (d >= -32768)
927
0
    return cmp_write_s16(ctx, (int16_t)d);
928
0
  if (d >= (-2147483647 - 1))
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
188
bool cmp_write_u8(cmp_ctx_t *ctx, uint8_t c) {
939
188
  if (!write_type_marker(ctx, U8_MARKER))
940
0
    return false;
941
942
188
  return ctx->write(ctx, &c, sizeof(uint8_t)) == sizeof(uint8_t);
943
188
}
944
945
869
bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s) {
946
869
  if (!write_type_marker(ctx, U16_MARKER))
947
0
    return false;
948
949
869
  s = be16(s);
950
951
869
  return ctx->write(ctx, &s, sizeof(uint16_t)) == sizeof(uint16_t);
952
869
}
953
954
47
bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i) {
955
47
  if (!write_type_marker(ctx, U32_MARKER))
956
0
    return false;
957
958
47
  i = be32(i);
959
960
47
  return ctx->write(ctx, &i, sizeof(uint32_t)) == sizeof(uint32_t);
961
47
}
962
963
24
bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l) {
964
24
  if (!write_type_marker(ctx, U64_MARKER))
965
0
    return false;
966
967
24
  l = be64(l);
968
969
24
  return ctx->write(ctx, &l, sizeof(uint64_t)) == sizeof(uint64_t);
970
24
}
971
972
12.7k
bool cmp_write_uinteger(cmp_ctx_t *ctx, uint64_t u) {
973
12.7k
  if (u <= 0x7F)
974
11.6k
    return cmp_write_pfix(ctx, (uint8_t)u);
975
1.12k
  if (u <= 0xFF)
976
188
    return cmp_write_u8(ctx, (uint8_t)u);
977
940
  if (u <= 0xFFFF)
978
869
    return cmp_write_u16(ctx, (uint16_t)u);
979
71
  if (u <= 0xFFFFFFFF)
980
47
    return cmp_write_u32(ctx, (uint32_t)u);
981
982
24
  return cmp_write_u64(ctx, u);
983
71
}
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
293
bool cmp_write_nil(cmp_ctx_t *ctx) {
1042
293
  return write_type_marker(ctx, NIL_MARKER);
1043
293
}
1044
1045
18
bool cmp_write_true(cmp_ctx_t *ctx) {
1046
18
  return write_type_marker(ctx, TRUE_MARKER);
1047
18
}
1048
1049
601
bool cmp_write_false(cmp_ctx_t *ctx) {
1050
601
  return write_type_marker(ctx, FALSE_MARKER);
1051
601
}
1052
1053
619
bool cmp_write_bool(cmp_ctx_t *ctx, bool b) {
1054
619
  if (b)
1055
18
    return cmp_write_true(ctx);
1056
1057
601
  return cmp_write_false(ctx);
1058
619
}
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
9.21k
bool cmp_write_bin8_marker(cmp_ctx_t *ctx, uint8_t size) {
1206
9.21k
  if (!write_type_marker(ctx, BIN8_MARKER))
1207
0
    return false;
1208
1209
9.21k
  if (ctx->write(ctx, &size, sizeof(uint8_t)) == sizeof(uint8_t))
1210
9.21k
    return true;
1211
1212
0
  ctx->error = CMP_ERROR_LENGTH_WRITING;
1213
0
  return false;
1214
9.21k
}
1215
1216
9.21k
bool cmp_write_bin8(cmp_ctx_t *ctx, const void *data, uint8_t size) {
1217
9.21k
  if (!cmp_write_bin8_marker(ctx, size))
1218
0
    return false;
1219
1220
9.21k
  if (size == 0)
1221
818
    return true;
1222
1223
8.39k
  if (ctx->write(ctx, data, size) == size)
1224
8.39k
    return true;
1225
1226
0
  ctx->error = CMP_ERROR_DATA_WRITING;
1227
0
  return false;
1228
8.39k
}
1229
1230
8
bool cmp_write_bin16_marker(cmp_ctx_t *ctx, uint16_t size) {
1231
8
  if (!write_type_marker(ctx, BIN16_MARKER))
1232
0
    return false;
1233
1234
8
  size = be16(size);
1235
1236
8
  if (ctx->write(ctx, &size, sizeof(uint16_t)) == sizeof(uint16_t))
1237
8
    return true;
1238
1239
0
  ctx->error = CMP_ERROR_LENGTH_WRITING;
1240
0
  return false;
1241
8
}
1242
1243
8
bool cmp_write_bin16(cmp_ctx_t *ctx, const void *data, uint16_t size) {
1244
8
  if (!cmp_write_bin16_marker(ctx, size))
1245
0
    return false;
1246
1247
8
  if (size == 0)
1248
0
    return true;
1249
1250
8
  if (ctx->write(ctx, data, size) == size)
1251
8
    return true;
1252
1253
0
  ctx->error = CMP_ERROR_DATA_WRITING;
1254
0
  return false;
1255
8
}
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
9.22k
bool cmp_write_bin(cmp_ctx_t *ctx, const void *data, uint32_t size) {
1294
9.22k
  if (size <= 0xFF)
1295
9.21k
    return cmp_write_bin8(ctx, data, (uint8_t)size);
1296
8
  if (size <= 0xFFFF)
1297
8
    return cmp_write_bin16(ctx, data, (uint16_t)size);
1298
1299
0
  return cmp_write_bin32(ctx, data, size);
1300
8
}
1301
1302
265k
bool cmp_write_fixarray(cmp_ctx_t *ctx, uint8_t size) {
1303
265k
  if (size <= FIXARRAY_SIZE)
1304
265k
    return write_fixed_value(ctx, FIXARRAY_MARKER | size);
1305
1306
0
  ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
1307
0
  return false;
1308
265k
}
1309
1310
24
bool cmp_write_array16(cmp_ctx_t *ctx, uint16_t size) {
1311
24
  if (!write_type_marker(ctx, ARRAY16_MARKER))
1312
0
    return false;
1313
1314
24
  size = be16(size);
1315
1316
24
  if (ctx->write(ctx, &size, sizeof(uint16_t)) == sizeof(uint16_t))
1317
24
    return true;
1318
1319
0
  ctx->error = CMP_ERROR_LENGTH_WRITING;
1320
0
  return false;
1321
24
}
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
265k
bool cmp_write_array(cmp_ctx_t *ctx, uint32_t size) {
1337
265k
  if (size <= FIXARRAY_SIZE)
1338
265k
    return cmp_write_fixarray(ctx, (uint8_t)size);
1339
24
  if (size <= 0xFFFF)
1340
24
    return cmp_write_array16(ctx, (uint16_t)size);
1341
1342
0
  return cmp_write_array32(ctx, size);
1343
24
}
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 <= 32767) {
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 <= 2147483647) {
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 <= 9223372036854775807) {
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
16.5k
bool cmp_read_uchar(cmp_ctx_t *ctx, uint8_t *c) {
2145
16.5k
  cmp_object_t obj;
2146
2147
16.5k
  if (!cmp_read_object(ctx, &obj))
2148
2.57k
    return false;
2149
2150
13.9k
  switch (obj.type) {
2151
11.7k
    case CMP_TYPE_POSITIVE_FIXNUM:
2152
12.5k
    case CMP_TYPE_UINT8: {
2153
12.5k
      *c = obj.as.u8;
2154
12.5k
      return true;
2155
11.7k
    }
2156
1.03k
    case CMP_TYPE_NEGATIVE_FIXNUM:
2157
1.05k
    case CMP_TYPE_SINT8: {
2158
1.05k
      if (obj.as.s8 >= 0) {
2159
20
        *c = (uint8_t)obj.as.s8;
2160
20
        return true;
2161
20
      }
2162
1.03k
      break;
2163
1.05k
    }
2164
1.03k
    default:
2165
382
      break;
2166
13.9k
  }
2167
2168
1.41k
  ctx->error = CMP_ERROR_INVALID_TYPE;
2169
1.41k
  return false;
2170
13.9k
}
2171
2172
30.5k
bool cmp_read_ushort(cmp_ctx_t *ctx, uint16_t *s) {
2173
30.5k
  cmp_object_t obj;
2174
2175
30.5k
  if (!cmp_read_object(ctx, &obj))
2176
298
    return false;
2177
2178
30.2k
  switch (obj.type) {
2179
24.2k
    case CMP_TYPE_POSITIVE_FIXNUM:
2180
25.6k
    case CMP_TYPE_UINT8: {
2181
25.6k
      *s = obj.as.u8;
2182
25.6k
      return true;
2183
24.2k
    }
2184
502
    case CMP_TYPE_UINT16: {
2185
502
      *s = obj.as.u16;
2186
502
      return true;
2187
24.2k
    }
2188
40
    case CMP_TYPE_NEGATIVE_FIXNUM:
2189
2.52k
    case CMP_TYPE_SINT8: {
2190
2.52k
      if (obj.as.s8 >= 0) {
2191
2.48k
        *s = (uint8_t)obj.as.s8;
2192
2.48k
        return true;
2193
2.48k
      }
2194
43
      break;
2195
2.52k
    }
2196
156
    case CMP_TYPE_SINT16: {
2197
156
      if (obj.as.s16 >= 0) {
2198
120
        *s = (uint16_t)obj.as.s16;
2199
120
        return true;
2200
120
      }
2201
36
      break;
2202
156
    }
2203
1.35k
    default:
2204
1.35k
      break;
2205
30.2k
  }
2206
2207
1.43k
  ctx->error = CMP_ERROR_INVALID_TYPE;
2208
1.43k
  return false;
2209
30.2k
}
2210
2211
20.7k
bool cmp_read_uint(cmp_ctx_t *ctx, uint32_t *i) {
2212
20.7k
  cmp_object_t obj;
2213
2214
20.7k
  if (!cmp_read_object(ctx, &obj))
2215
1.97k
    return false;
2216
2217
18.7k
  switch (obj.type) {
2218
14.8k
    case CMP_TYPE_POSITIVE_FIXNUM:
2219
15.1k
    case CMP_TYPE_UINT8: {
2220
15.1k
      *i = obj.as.u8;
2221
15.1k
      return true;
2222
14.8k
    }
2223
154
    case CMP_TYPE_UINT16: {
2224
154
      *i = obj.as.u16;
2225
154
      return true;
2226
14.8k
    }
2227
2.41k
    case CMP_TYPE_UINT32: {
2228
2.41k
      *i = obj.as.u32;
2229
2.41k
      return true;
2230
14.8k
    }
2231
394
    case CMP_TYPE_NEGATIVE_FIXNUM:
2232
661
    case CMP_TYPE_SINT8: {
2233
661
      if (obj.as.s8 >= 0) {
2234
266
        *i = (uint8_t)obj.as.s8;
2235
266
        return true;
2236
266
      }
2237
395
      break;
2238
661
    }
2239
395
    case CMP_TYPE_SINT16: {
2240
118
      if (obj.as.s16 >= 0) {
2241
107
        *i = (uint16_t)obj.as.s16;
2242
107
        return true;
2243
107
      }
2244
11
      break;
2245
118
    }
2246
67
    case CMP_TYPE_SINT32: {
2247
67
      if (obj.as.s32 >= 0) {
2248
32
        *i = (uint32_t)obj.as.s32;
2249
32
        return true;
2250
32
      }
2251
35
      break;
2252
67
    }
2253
187
    default:
2254
187
      break;
2255
18.7k
  }
2256
2257
628
  ctx->error = CMP_ERROR_INVALID_TYPE;
2258
628
  return false;
2259
18.7k
}
2260
2261
148
bool cmp_read_ulong(cmp_ctx_t *ctx, uint64_t *u) {
2262
148
  cmp_object_t obj;
2263
2264
148
  if (!cmp_read_object(ctx, &obj))
2265
6
    return false;
2266
2267
142
  switch (obj.type) {
2268
42
    case CMP_TYPE_POSITIVE_FIXNUM:
2269
53
    case CMP_TYPE_UINT8: {
2270
53
      *u = obj.as.u8;
2271
53
      return true;
2272
42
    }
2273
4
    case CMP_TYPE_UINT16: {
2274
4
      *u = obj.as.u16;
2275
4
      return true;
2276
42
    }
2277
6
    case CMP_TYPE_UINT32: {
2278
6
      *u = obj.as.u32;
2279
6
      return true;
2280
42
    }
2281
3
    case CMP_TYPE_UINT64: {
2282
3
      *u = obj.as.u64;
2283
3
      return true;
2284
42
    }
2285
1
    case CMP_TYPE_NEGATIVE_FIXNUM:
2286
15
    case CMP_TYPE_SINT8: {
2287
15
      if (obj.as.s8 >= 0) {
2288
14
        *u = (uint8_t)obj.as.s8;
2289
14
        return true;
2290
14
      }
2291
1
      break;
2292
15
    }
2293
26
    case CMP_TYPE_SINT16: {
2294
26
      if (obj.as.s16 >= 0) {
2295
25
        *u = (uint16_t)obj.as.s16;
2296
25
        return true;
2297
25
      }
2298
1
      break;
2299
26
    }
2300
4
    case CMP_TYPE_SINT32: {
2301
4
      if (obj.as.s32 >= 0) {
2302
3
        *u = (uint32_t)obj.as.s32;
2303
3
        return true;
2304
3
      }
2305
1
      break;
2306
4
    }
2307
30
    case CMP_TYPE_SINT64: {
2308
30
      if (obj.as.s64 >= 0) {
2309
29
        *u = (uint64_t)obj.as.s64;
2310
29
        return true;
2311
29
      }
2312
1
      break;
2313
30
    }
2314
1
    default:
2315
1
      break;
2316
142
  }
2317
2318
5
  ctx->error = CMP_ERROR_INVALID_TYPE;
2319
5
  return false;
2320
142
}
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
94
bool cmp_read_nil(cmp_ctx_t *ctx) {
2383
94
  cmp_object_t obj;
2384
2385
94
  if (!cmp_read_object(ctx, &obj))
2386
5
    return false;
2387
2388
89
  if (obj.type == CMP_TYPE_NIL)
2389
69
    return true;
2390
2391
20
  ctx->error = CMP_ERROR_INVALID_TYPE;
2392
20
  return false;
2393
89
}
2394
2395
11.7k
bool cmp_read_bool(cmp_ctx_t *ctx, bool *b) {
2396
11.7k
  cmp_object_t obj;
2397
2398
11.7k
  if (!cmp_read_object(ctx, &obj))
2399
105
    return false;
2400
2401
11.6k
  if (obj.type != CMP_TYPE_BOOLEAN) {
2402
1.03k
    ctx->error = CMP_ERROR_INVALID_TYPE;
2403
1.03k
    return false;
2404
1.03k
  }
2405
2406
10.6k
  if (obj.as.boolean) {
2407
3.36k
    *b = true;
2408
7.29k
  } else {
2409
7.29k
    *b = false;
2410
7.29k
  }
2411
2412
10.6k
  return true;
2413
11.6k
}
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
7.23k
bool cmp_read_bin_size(cmp_ctx_t *ctx, uint32_t *size) {
2480
7.23k
  cmp_object_t obj;
2481
2482
7.23k
  if (!cmp_read_object(ctx, &obj))
2483
692
    return false;
2484
2485
6.54k
  switch (obj.type) {
2486
4.98k
    case CMP_TYPE_BIN8:
2487
5.40k
    case CMP_TYPE_BIN16:
2488
5.49k
    case CMP_TYPE_BIN32: {
2489
5.49k
      *size = obj.as.bin_size;
2490
5.49k
      return true;
2491
5.40k
    }
2492
1.05k
    default: {
2493
1.05k
      ctx->error = CMP_ERROR_INVALID_TYPE;
2494
1.05k
      return false;
2495
5.40k
    }
2496
6.54k
  }
2497
6.54k
}
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
47.8k
bool cmp_read_array(cmp_ctx_t *ctx, uint32_t *size) {
2520
47.8k
  cmp_object_t obj;
2521
2522
47.8k
  if (!cmp_read_object(ctx, &obj))
2523
196
    return false;
2524
2525
47.6k
  switch (obj.type) {
2526
44.6k
    case CMP_TYPE_FIXARRAY:
2527
44.6k
    case CMP_TYPE_ARRAY16:
2528
44.7k
    case CMP_TYPE_ARRAY32: {
2529
44.7k
      *size = obj.as.array_size;
2530
44.7k
      return true;
2531
44.6k
    }
2532
2.94k
    default: {
2533
2.94k
      ctx->error = CMP_ERROR_INVALID_TYPE;
2534
2.94k
      return false;
2535
44.6k
    }
2536
47.6k
  }
2537
47.6k
}
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
134k
bool cmp_read_object(cmp_ctx_t *ctx, cmp_object_t *obj) {
2811
134k
  uint8_t type_marker = 0;
2812
2813
134k
  if (!read_type_marker(ctx, &type_marker))
2814
1.58k
    return false;
2815
2816
133k
  if (!type_marker_to_cmp_type(type_marker, &obj->type)) {
2817
75
    ctx->error = CMP_ERROR_INVALID_TYPE;
2818
75
    return false;
2819
75
  }
2820
2821
133k
  return read_obj_data(ctx, type_marker, obj);
2822
133k
}
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 <= 32767) {
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 <= 2147483647) {
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 <= 9223372036854775807) {
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: */