1/*
2 * Copyright (c) 2015-2021 Nicholas Fraser and the MPack authors
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 * the Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22#define MPACK_INTERNAL 1
23
24#include "mpack-expect.h"
25
26MPACK_SILENCE_WARNINGS_BEGIN
27
28#if MPACK_EXPECT
29
30
31// Helpers
32
33MPACK_STATIC_INLINE uint8_t mpack_expect_native_u8(mpack_reader_t* reader) {
34 if (mpack_reader_error(reader) != mpack_ok)
35 return 0;
36 uint8_t type;
37 if (!mpack_reader_ensure(reader, sizeof(type)))
38 return 0;
39 type = mpack_load_u8(reader->data);
40 reader->data += sizeof(type);
41 return type;
42}
43
44#if !MPACK_OPTIMIZE_FOR_SIZE
45MPACK_STATIC_INLINE uint16_t mpack_expect_native_u16(mpack_reader_t* reader) {
46 if (mpack_reader_error(reader) != mpack_ok)
47 return 0;
48 uint16_t type;
49 if (!mpack_reader_ensure(reader, sizeof(type)))
50 return 0;
51 type = mpack_load_u16(reader->data);
52 reader->data += sizeof(type);
53 return type;
54}
55
56MPACK_STATIC_INLINE uint32_t mpack_expect_native_u32(mpack_reader_t* reader) {
57 if (mpack_reader_error(reader) != mpack_ok)
58 return 0;
59 uint32_t type;
60 if (!mpack_reader_ensure(reader, sizeof(type)))
61 return 0;
62 type = mpack_load_u32(reader->data);
63 reader->data += sizeof(type);
64 return type;
65}
66#endif
67
68MPACK_STATIC_INLINE uint8_t mpack_expect_type_byte(mpack_reader_t* reader) {
69 mpack_reader_track_element(reader);
70 return mpack_expect_native_u8(reader);
71}
72
73
74// Basic Number Functions
75
76uint8_t mpack_expect_u8(mpack_reader_t* reader) {
77 mpack_tag_t var = mpack_read_tag(reader);
78 if (var.type == mpack_type_uint) {
79 if (var.v.u <= MPACK_UINT8_MAX)
80 return (uint8_t)var.v.u;
81 } else if (var.type == mpack_type_int) {
82 if (var.v.i >= 0 && var.v.i <= MPACK_UINT8_MAX)
83 return (uint8_t)var.v.i;
84 }
85 mpack_reader_flag_error(reader, mpack_error_type);
86 return 0;
87}
88
89uint16_t mpack_expect_u16(mpack_reader_t* reader) {
90 mpack_tag_t var = mpack_read_tag(reader);
91 if (var.type == mpack_type_uint) {
92 if (var.v.u <= MPACK_UINT16_MAX)
93 return (uint16_t)var.v.u;
94 } else if (var.type == mpack_type_int) {
95 if (var.v.i >= 0 && var.v.i <= MPACK_UINT16_MAX)
96 return (uint16_t)var.v.i;
97 }
98 mpack_reader_flag_error(reader, mpack_error_type);
99 return 0;
100}
101
102uint32_t mpack_expect_u32(mpack_reader_t* reader) {
103 mpack_tag_t var = mpack_read_tag(reader);
104 if (var.type == mpack_type_uint) {
105 if (var.v.u <= MPACK_UINT32_MAX)
106 return (uint32_t)var.v.u;
107 } else if (var.type == mpack_type_int) {
108 if (var.v.i >= 0 && var.v.i <= MPACK_UINT32_MAX)
109 return (uint32_t)var.v.i;
110 }
111 mpack_reader_flag_error(reader, mpack_error_type);
112 return 0;
113}
114
115uint64_t mpack_expect_u64(mpack_reader_t* reader) {
116 mpack_tag_t var = mpack_read_tag(reader);
117 if (var.type == mpack_type_uint) {
118 return var.v.u;
119 } else if (var.type == mpack_type_int) {
120 if (var.v.i >= 0)
121 return (uint64_t)var.v.i;
122 }
123 mpack_reader_flag_error(reader, mpack_error_type);
124 return 0;
125}
126
127int8_t mpack_expect_i8(mpack_reader_t* reader) {
128 mpack_tag_t var = mpack_read_tag(reader);
129 if (var.type == mpack_type_uint) {
130 if (var.v.u <= MPACK_INT8_MAX)
131 return (int8_t)var.v.u;
132 } else if (var.type == mpack_type_int) {
133 if (var.v.i >= MPACK_INT8_MIN && var.v.i <= MPACK_INT8_MAX)
134 return (int8_t)var.v.i;
135 }
136 mpack_reader_flag_error(reader, mpack_error_type);
137 return 0;
138}
139
140int16_t mpack_expect_i16(mpack_reader_t* reader) {
141 mpack_tag_t var = mpack_read_tag(reader);
142 if (var.type == mpack_type_uint) {
143 if (var.v.u <= MPACK_INT16_MAX)
144 return (int16_t)var.v.u;
145 } else if (var.type == mpack_type_int) {
146 if (var.v.i >= MPACK_INT16_MIN && var.v.i <= MPACK_INT16_MAX)
147 return (int16_t)var.v.i;
148 }
149 mpack_reader_flag_error(reader, mpack_error_type);
150 return 0;
151}
152
153int32_t mpack_expect_i32(mpack_reader_t* reader) {
154 mpack_tag_t var = mpack_read_tag(reader);
155 if (var.type == mpack_type_uint) {
156 if (var.v.u <= MPACK_INT32_MAX)
157 return (int32_t)var.v.u;
158 } else if (var.type == mpack_type_int) {
159 if (var.v.i >= MPACK_INT32_MIN && var.v.i <= MPACK_INT32_MAX)
160 return (int32_t)var.v.i;
161 }
162 mpack_reader_flag_error(reader, mpack_error_type);
163 return 0;
164}
165
166int64_t mpack_expect_i64(mpack_reader_t* reader) {
167 mpack_tag_t var = mpack_read_tag(reader);
168 if (var.type == mpack_type_uint) {
169 if (var.v.u <= MPACK_INT64_MAX)
170 return (int64_t)var.v.u;
171 } else if (var.type == mpack_type_int) {
172 return var.v.i;
173 }
174 mpack_reader_flag_error(reader, mpack_error_type);
175 return 0;
176}
177
178#if MPACK_FLOAT
179float mpack_expect_float(mpack_reader_t* reader) {
180 mpack_tag_t var = mpack_read_tag(reader);
181 if (var.type == mpack_type_uint)
182 return (float)var.v.u;
183 if (var.type == mpack_type_int)
184 return (float)var.v.i;
185 if (var.type == mpack_type_float)
186 return var.v.f;
187
188 if (var.type == mpack_type_double) {
189 #if MPACK_DOUBLE
190 return (float)var.v.d;
191 #else
192 return mpack_shorten_raw_double_to_float(var.v.d);
193 #endif
194 }
195
196 mpack_reader_flag_error(reader, mpack_error_type);
197 return 0.0f;
198}
199#endif
200
201#if MPACK_DOUBLE
202double mpack_expect_double(mpack_reader_t* reader) {
203 mpack_tag_t var = mpack_read_tag(reader);
204 if (var.type == mpack_type_uint)
205 return (double)var.v.u;
206 else if (var.type == mpack_type_int)
207 return (double)var.v.i;
208 else if (var.type == mpack_type_float)
209 return (double)var.v.f;
210 else if (var.type == mpack_type_double)
211 return var.v.d;
212 mpack_reader_flag_error(reader, mpack_error_type);
213 return 0.0;
214}
215#endif
216
217#if MPACK_FLOAT
218float mpack_expect_float_strict(mpack_reader_t* reader) {
219 mpack_tag_t var = mpack_read_tag(reader);
220 if (var.type == mpack_type_float)
221 return var.v.f;
222 mpack_reader_flag_error(reader, mpack_error_type);
223 return 0.0f;
224}
225#endif
226
227#if MPACK_DOUBLE
228double mpack_expect_double_strict(mpack_reader_t* reader) {
229 mpack_tag_t var = mpack_read_tag(reader);
230 if (var.type == mpack_type_float)
231 return (double)var.v.f;
232 else if (var.type == mpack_type_double)
233 return var.v.d;
234 mpack_reader_flag_error(reader, mpack_error_type);
235 return 0.0;
236}
237#endif
238
239#if !MPACK_FLOAT
240uint32_t mpack_expect_raw_float(mpack_reader_t* reader) {
241 mpack_tag_t var = mpack_read_tag(reader);
242 if (var.type == mpack_type_float)
243 return var.v.f;
244 mpack_reader_flag_error(reader, mpack_error_type);
245 return 0;
246}
247#endif
248
249#if !MPACK_DOUBLE
250uint64_t mpack_expect_raw_double(mpack_reader_t* reader) {
251 mpack_tag_t var = mpack_read_tag(reader);
252 if (var.type == mpack_type_double)
253 return var.v.d;
254 mpack_reader_flag_error(reader, mpack_error_type);
255 return 0;
256}
257#endif
258
259
260// Ranged Number Functions
261//
262// All ranged functions are identical other than the type, so we
263// define their content with a macro. The prototypes are still written
264// out in full to support ctags/IDE tools.
265
266#define MPACK_EXPECT_RANGE_IMPL(name, type_t) \
267 \
268 /* make sure the range is sensible */ \
269 mpack_assert(min_value <= max_value, \
270 "min_value %i must be less than or equal to max_value %i", \
271 min_value, max_value); \
272 \
273 /* read the value */ \
274 type_t val = mpack_expect_##name(reader); \
275 if (mpack_reader_error(reader) != mpack_ok) \
276 return min_value; \
277 \
278 /* make sure it fits */ \
279 if (val < min_value || val > max_value) { \
280 mpack_reader_flag_error(reader, mpack_error_type); \
281 return min_value; \
282 } \
283 \
284 return val;
285
286uint8_t mpack_expect_u8_range(mpack_reader_t* reader, uint8_t min_value, uint8_t max_value) {MPACK_EXPECT_RANGE_IMPL(u8, uint8_t)}
287uint16_t mpack_expect_u16_range(mpack_reader_t* reader, uint16_t min_value, uint16_t max_value) {MPACK_EXPECT_RANGE_IMPL(u16, uint16_t)}
288uint32_t mpack_expect_u32_range(mpack_reader_t* reader, uint32_t min_value, uint32_t max_value) {MPACK_EXPECT_RANGE_IMPL(u32, uint32_t)}
289uint64_t mpack_expect_u64_range(mpack_reader_t* reader, uint64_t min_value, uint64_t max_value) {MPACK_EXPECT_RANGE_IMPL(u64, uint64_t)}
290
291int8_t mpack_expect_i8_range(mpack_reader_t* reader, int8_t min_value, int8_t max_value) {MPACK_EXPECT_RANGE_IMPL(i8, int8_t)}
292int16_t mpack_expect_i16_range(mpack_reader_t* reader, int16_t min_value, int16_t max_value) {MPACK_EXPECT_RANGE_IMPL(i16, int16_t)}
293int32_t mpack_expect_i32_range(mpack_reader_t* reader, int32_t min_value, int32_t max_value) {MPACK_EXPECT_RANGE_IMPL(i32, int32_t)}
294int64_t mpack_expect_i64_range(mpack_reader_t* reader, int64_t min_value, int64_t max_value) {MPACK_EXPECT_RANGE_IMPL(i64, int64_t)}
295
296#if MPACK_FLOAT
297float mpack_expect_float_range(mpack_reader_t* reader, float min_value, float max_value) {MPACK_EXPECT_RANGE_IMPL(float, float)}
298#endif
299#if MPACK_DOUBLE
300double mpack_expect_double_range(mpack_reader_t* reader, double min_value, double max_value) {MPACK_EXPECT_RANGE_IMPL(double, double)}
301#endif
302
303uint32_t mpack_expect_map_range(mpack_reader_t* reader, uint32_t min_value, uint32_t max_value) {MPACK_EXPECT_RANGE_IMPL(map, uint32_t)}
304uint32_t mpack_expect_array_range(mpack_reader_t* reader, uint32_t min_value, uint32_t max_value) {MPACK_EXPECT_RANGE_IMPL(array, uint32_t)}
305
306
307// Matching Number Functions
308
309void mpack_expect_uint_match(mpack_reader_t* reader, uint64_t value) {
310 if (mpack_expect_u64(reader) != value)
311 mpack_reader_flag_error(reader, mpack_error_type);
312}
313
314void mpack_expect_int_match(mpack_reader_t* reader, int64_t value) {
315 if (mpack_expect_i64(reader) != value)
316 mpack_reader_flag_error(reader, mpack_error_type);
317}
318
319
320// Other Basic Types
321
322void mpack_expect_nil(mpack_reader_t* reader) {
323 if (mpack_expect_type_byte(reader) != 0xc0)
324 mpack_reader_flag_error(reader, mpack_error_type);
325}
326
327bool mpack_expect_bool(mpack_reader_t* reader) {
328 uint8_t type = mpack_expect_type_byte(reader);
329 if ((type & ~1) != 0xc2)
330 mpack_reader_flag_error(reader, mpack_error_type);
331 return (bool)(type & 1);
332}
333
334void mpack_expect_true(mpack_reader_t* reader) {
335 if (mpack_expect_bool(reader) != true)
336 mpack_reader_flag_error(reader, mpack_error_type);
337}
338
339void mpack_expect_false(mpack_reader_t* reader) {
340 if (mpack_expect_bool(reader) != false)
341 mpack_reader_flag_error(reader, mpack_error_type);
342}
343
344#if MPACK_EXTENSIONS
345mpack_timestamp_t mpack_expect_timestamp(mpack_reader_t* reader) {
346 mpack_timestamp_t zero = {0, 0};
347
348 mpack_tag_t tag = mpack_read_tag(reader);
349 if (tag.type != mpack_type_ext) {
350 mpack_reader_flag_error(reader, mpack_error_type);
351 return zero;
352 }
353 if (mpack_tag_ext_exttype(&tag) != MPACK_EXTTYPE_TIMESTAMP) {
354 mpack_reader_flag_error(reader, mpack_error_type);
355 return zero;
356 }
357
358 return mpack_read_timestamp(reader, mpack_tag_ext_length(&tag));
359}
360
361int64_t mpack_expect_timestamp_truncate(mpack_reader_t* reader) {
362 return mpack_expect_timestamp(reader).seconds;
363}
364#endif
365
366
367// Compound Types
368
369uint32_t mpack_expect_map(mpack_reader_t* reader) {
370 mpack_tag_t var = mpack_read_tag(reader);
371 if (var.type == mpack_type_map)
372 return var.v.n;
373 mpack_reader_flag_error(reader, mpack_error_type);
374 return 0;
375}
376
377void mpack_expect_map_match(mpack_reader_t* reader, uint32_t count) {
378 if (mpack_expect_map(reader) != count)
379 mpack_reader_flag_error(reader, mpack_error_type);
380}
381
382bool mpack_expect_map_or_nil(mpack_reader_t* reader, uint32_t* count) {
383 mpack_assert(count != NULL, "count cannot be NULL");
384
385 mpack_tag_t var = mpack_read_tag(reader);
386 if (var.type == mpack_type_nil) {
387 *count = 0;
388 return false;
389 }
390 if (var.type == mpack_type_map) {
391 *count = var.v.n;
392 return true;
393 }
394 mpack_reader_flag_error(reader, mpack_error_type);
395 *count = 0;
396 return false;
397}
398
399bool mpack_expect_map_max_or_nil(mpack_reader_t* reader, uint32_t max_count, uint32_t* count) {
400 mpack_assert(count != NULL, "count cannot be NULL");
401
402 bool has_map = mpack_expect_map_or_nil(reader, count);
403 if (has_map && *count > max_count) {
404 *count = 0;
405 mpack_reader_flag_error(reader, mpack_error_type);
406 return false;
407 }
408 return has_map;
409}
410
411uint32_t mpack_expect_array(mpack_reader_t* reader) {
412 mpack_tag_t var = mpack_read_tag(reader);
413 if (var.type == mpack_type_array)
414 return var.v.n;
415 mpack_reader_flag_error(reader, mpack_error_type);
416 return 0;
417}
418
419void mpack_expect_array_match(mpack_reader_t* reader, uint32_t count) {
420 if (mpack_expect_array(reader) != count)
421 mpack_reader_flag_error(reader, mpack_error_type);
422}
423
424bool mpack_expect_array_or_nil(mpack_reader_t* reader, uint32_t* count) {
425 mpack_assert(count != NULL, "count cannot be NULL");
426
427 mpack_tag_t var = mpack_read_tag(reader);
428 if (var.type == mpack_type_nil) {
429 *count = 0;
430 return false;
431 }
432 if (var.type == mpack_type_array) {
433 *count = var.v.n;
434 return true;
435 }
436 mpack_reader_flag_error(reader, mpack_error_type);
437 *count = 0;
438 return false;
439}
440
441bool mpack_expect_array_max_or_nil(mpack_reader_t* reader, uint32_t max_count, uint32_t* count) {
442 mpack_assert(count != NULL, "count cannot be NULL");
443
444 bool has_array = mpack_expect_array_or_nil(reader, count);
445 if (has_array && *count > max_count) {
446 *count = 0;
447 mpack_reader_flag_error(reader, mpack_error_type);
448 return false;
449 }
450 return has_array;
451}
452
453#ifdef MPACK_MALLOC
454void* mpack_expect_array_alloc_impl(mpack_reader_t* reader, size_t element_size, uint32_t max_count, uint32_t* out_count, bool allow_nil) {
455 mpack_assert(out_count != NULL, "out_count cannot be NULL");
456 *out_count = 0;
457
458 uint32_t count;
459 bool has_array = true;
460 if (allow_nil)
461 has_array = mpack_expect_array_max_or_nil(reader, max_count, &count);
462 else
463 count = mpack_expect_array_max(reader, max_count);
464 if (mpack_reader_error(reader))
465 return NULL;
466
467 // size 0 is not an error; we return NULL for no elements.
468 if (count == 0) {
469 // we call mpack_done_array() automatically ONLY if we are using
470 // the _or_nil variant. this is the only way to allow nil and empty
471 // to work the same way.
472 if (allow_nil && has_array)
473 mpack_done_array(reader);
474 return NULL;
475 }
476
477 void* p = MPACK_MALLOC(element_size * count);
478 if (p == NULL) {
479 mpack_reader_flag_error(reader, mpack_error_memory);
480 return NULL;
481 }
482
483 *out_count = count;
484 return p;
485}
486#endif
487
488
489// Str, Bin and Ext Functions
490
491uint32_t mpack_expect_str(mpack_reader_t* reader) {
492 #if MPACK_OPTIMIZE_FOR_SIZE
493 mpack_tag_t var = mpack_read_tag(reader);
494 if (var.type == mpack_type_str)
495 return var.v.l;
496 mpack_reader_flag_error(reader, mpack_error_type);
497 return 0;
498 #else
499 uint8_t type = mpack_expect_type_byte(reader);
500 uint32_t count;
501
502 if ((type >> 5) == 5) {
503 count = type & (uint8_t)~0xe0;
504 } else if (type == 0xd9) {
505 count = mpack_expect_native_u8(reader);
506 } else if (type == 0xda) {
507 count = mpack_expect_native_u16(reader);
508 } else if (type == 0xdb) {
509 count = mpack_expect_native_u32(reader);
510 } else {
511 mpack_reader_flag_error(reader, mpack_error_type);
512 return 0;
513 }
514
515 #if MPACK_READ_TRACKING
516 mpack_reader_flag_if_error(reader, mpack_track_push(&reader->track, mpack_type_str, count));
517 #endif
518 return count;
519 #endif
520}
521
522size_t mpack_expect_str_buf(mpack_reader_t* reader, char* buf, size_t bufsize) {
523 mpack_assert(buf != NULL, "buf cannot be NULL");
524
525 size_t length = mpack_expect_str(reader);
526 if (mpack_reader_error(reader))
527 return 0;
528
529 if (length > bufsize) {
530 mpack_reader_flag_error(reader, mpack_error_too_big);
531 return 0;
532 }
533
534 mpack_read_bytes(reader, buf, length);
535 if (mpack_reader_error(reader))
536 return 0;
537
538 mpack_done_str(reader);
539 return length;
540}
541
542size_t mpack_expect_utf8(mpack_reader_t* reader, char* buf, size_t size) {
543 mpack_assert(buf != NULL, "buf cannot be NULL");
544
545 size_t length = mpack_expect_str_buf(reader, buf, size);
546
547 if (!mpack_utf8_check(buf, length)) {
548 mpack_reader_flag_error(reader, mpack_error_type);
549 return 0;
550 }
551
552 return length;
553}
554
555uint32_t mpack_expect_bin(mpack_reader_t* reader) {
556 mpack_tag_t var = mpack_read_tag(reader);
557 if (var.type == mpack_type_bin)
558 return var.v.l;
559 mpack_reader_flag_error(reader, mpack_error_type);
560 return 0;
561}
562
563size_t mpack_expect_bin_buf(mpack_reader_t* reader, char* buf, size_t bufsize) {
564 mpack_assert(buf != NULL, "buf cannot be NULL");
565
566 size_t binsize = mpack_expect_bin(reader);
567 if (mpack_reader_error(reader))
568 return 0;
569 if (binsize > bufsize) {
570 mpack_reader_flag_error(reader, mpack_error_too_big);
571 return 0;
572 }
573 mpack_read_bytes(reader, buf, binsize);
574 if (mpack_reader_error(reader))
575 return 0;
576 mpack_done_bin(reader);
577 return binsize;
578}
579
580void mpack_expect_bin_size_buf(mpack_reader_t* reader, char* buf, uint32_t size) {
581 mpack_assert(buf != NULL, "buf cannot be NULL");
582 mpack_expect_bin_size(reader, size);
583 mpack_read_bytes(reader, buf, size);
584 mpack_done_bin(reader);
585}
586
587#if MPACK_EXTENSIONS
588uint32_t mpack_expect_ext(mpack_reader_t* reader, int8_t* type) {
589 mpack_tag_t var = mpack_read_tag(reader);
590 if (var.type == mpack_type_ext) {
591 *type = mpack_tag_ext_exttype(&var);
592 return mpack_tag_ext_length(&var);
593 }
594 *type = 0;
595 mpack_reader_flag_error(reader, mpack_error_type);
596 return 0;
597}
598
599size_t mpack_expect_ext_buf(mpack_reader_t* reader, int8_t* type, char* buf, size_t bufsize) {
600 mpack_assert(buf != NULL, "buf cannot be NULL");
601
602 size_t extsize = mpack_expect_ext(reader, type);
603 if (mpack_reader_error(reader))
604 return 0;
605 if (extsize > bufsize) {
606 *type = 0;
607 mpack_reader_flag_error(reader, mpack_error_too_big);
608 return 0;
609 }
610 mpack_read_bytes(reader, buf, extsize);
611 if (mpack_reader_error(reader)) {
612 *type = 0;
613 return 0;
614 }
615 mpack_done_ext(reader);
616 return extsize;
617}
618#endif
619
620void mpack_expect_cstr(mpack_reader_t* reader, char* buf, size_t bufsize) {
621 uint32_t length = mpack_expect_str(reader);
622 mpack_read_cstr(reader, buf, bufsize, length);
623 mpack_done_str(reader);
624}
625
626void mpack_expect_utf8_cstr(mpack_reader_t* reader, char* buf, size_t bufsize) {
627 uint32_t length = mpack_expect_str(reader);
628 mpack_read_utf8_cstr(reader, buf, bufsize, length);
629 mpack_done_str(reader);
630}
631
632#ifdef MPACK_MALLOC
633static char* mpack_expect_cstr_alloc_unchecked(mpack_reader_t* reader, size_t maxsize, size_t* out_length) {
634 mpack_assert(out_length != NULL, "out_length cannot be NULL");
635 *out_length = 0;
636
637 // make sure argument makes sense
638 if (maxsize < 1) {
639 mpack_break("maxsize is zero; you must have room for at least a null-terminator");
640 mpack_reader_flag_error(reader, mpack_error_bug);
641 return NULL;
642 }
643
644 if (SIZE_MAX < MPACK_UINT32_MAX) {
645 if (maxsize > SIZE_MAX)
646 maxsize = SIZE_MAX;
647 } else {
648 if (maxsize > (size_t)MPACK_UINT32_MAX)
649 maxsize = (size_t)MPACK_UINT32_MAX;
650 }
651
652 size_t length = mpack_expect_str_max(reader, (uint32_t)maxsize - 1);
653 char* str = mpack_read_bytes_alloc_impl(reader, length, true);
654 mpack_done_str(reader);
655
656 if (str)
657 *out_length = length;
658 return str;
659}
660
661char* mpack_expect_cstr_alloc(mpack_reader_t* reader, size_t maxsize) {
662 size_t length;
663 char* str = mpack_expect_cstr_alloc_unchecked(reader, maxsize, &length);
664
665 if (str && !mpack_str_check_no_null(str, length)) {
666 MPACK_FREE(str);
667 mpack_reader_flag_error(reader, mpack_error_type);
668 return NULL;
669 }
670
671 return str;
672}
673
674char* mpack_expect_utf8_cstr_alloc(mpack_reader_t* reader, size_t maxsize) {
675 size_t length;
676 char* str = mpack_expect_cstr_alloc_unchecked(reader, maxsize, &length);
677
678 if (str && !mpack_utf8_check_no_null(str, length)) {
679 MPACK_FREE(str);
680 mpack_reader_flag_error(reader, mpack_error_type);
681 return NULL;
682 }
683
684 return str;
685}
686#endif
687
688void mpack_expect_str_match(mpack_reader_t* reader, const char* str, size_t len) {
689 mpack_assert(str != NULL, "str cannot be NULL");
690
691 // expect a str the correct length
692 if (len > MPACK_UINT32_MAX)
693 mpack_reader_flag_error(reader, mpack_error_type);
694 mpack_expect_str_length(reader, (uint32_t)len);
695 if (mpack_reader_error(reader))
696 return;
697 mpack_reader_track_bytes(reader, (uint32_t)len);
698
699 // check each byte one by one (matched strings are likely to be very small)
700 for (; len > 0; --len) {
701 if (mpack_expect_native_u8(reader) != *str++) {
702 mpack_reader_flag_error(reader, mpack_error_type);
703 return;
704 }
705 }
706
707 mpack_done_str(reader);
708}
709
710void mpack_expect_tag(mpack_reader_t* reader, mpack_tag_t expected) {
711 mpack_tag_t actual = mpack_read_tag(reader);
712 if (!mpack_tag_equal(actual, expected))
713 mpack_reader_flag_error(reader, mpack_error_type);
714}
715
716#ifdef MPACK_MALLOC
717char* mpack_expect_bin_alloc(mpack_reader_t* reader, size_t maxsize, size_t* size) {
718 mpack_assert(size != NULL, "size cannot be NULL");
719 *size = 0;
720
721 if (SIZE_MAX < MPACK_UINT32_MAX) {
722 if (maxsize > SIZE_MAX)
723 maxsize = SIZE_MAX;
724 } else {
725 if (maxsize > (size_t)MPACK_UINT32_MAX)
726 maxsize = (size_t)MPACK_UINT32_MAX;
727 }
728
729 size_t length = mpack_expect_bin_max(reader, (uint32_t)maxsize);
730 if (mpack_reader_error(reader))
731 return NULL;
732
733 char* data = mpack_read_bytes_alloc(reader, length);
734 mpack_done_bin(reader);
735
736 if (data)
737 *size = length;
738 return data;
739}
740#endif
741
742#if MPACK_EXTENSIONS && defined(MPACK_MALLOC)
743char* mpack_expect_ext_alloc(mpack_reader_t* reader, int8_t* type, size_t maxsize, size_t* size) {
744 mpack_assert(size != NULL, "size cannot be NULL");
745 *size = 0;
746
747 if (SIZE_MAX < MPACK_UINT32_MAX) {
748 if (maxsize > SIZE_MAX)
749 maxsize = SIZE_MAX;
750 } else {
751 if (maxsize > (size_t)MPACK_UINT32_MAX)
752 maxsize = (size_t)MPACK_UINT32_MAX;
753 }
754
755 size_t length = mpack_expect_ext_max(reader, type, (uint32_t)maxsize);
756 if (mpack_reader_error(reader))
757 return NULL;
758
759 char* data = mpack_read_bytes_alloc(reader, length);
760 mpack_done_ext(reader);
761
762 if (data) {
763 *size = length;
764 } else {
765 *type = 0;
766 }
767 return data;
768}
769#endif
770
771size_t mpack_expect_enum(mpack_reader_t* reader, const char* strings[], size_t count) {
772
773 // read the string in-place
774 size_t keylen = mpack_expect_str(reader);
775 const char* key = mpack_read_bytes_inplace(reader, keylen);
776 mpack_done_str(reader);
777 if (mpack_reader_error(reader) != mpack_ok)
778 return count;
779
780 // find what key it matches
781 size_t i;
782 for (i = 0; i < count; ++i) {
783 const char* other = strings[i];
784 size_t otherlen = mpack_strlen(other);
785 if (keylen == otherlen && mpack_memcmp(key, other, keylen) == 0)
786 return i;
787 }
788
789 // no matches
790 mpack_reader_flag_error(reader, mpack_error_type);
791 return count;
792}
793
794size_t mpack_expect_enum_optional(mpack_reader_t* reader, const char* strings[], size_t count) {
795 if (mpack_reader_error(reader) != mpack_ok)
796 return count;
797
798 mpack_assert(count != 0, "count cannot be zero; no strings are valid!");
799 mpack_assert(strings != NULL, "strings cannot be NULL");
800
801 // the key is only recognized if it is a string
802 if (mpack_peek_tag(reader).type != mpack_type_str) {
803 mpack_discard(reader);
804 return count;
805 }
806
807 // read the string in-place
808 size_t keylen = mpack_expect_str(reader);
809 const char* key = mpack_read_bytes_inplace(reader, keylen);
810 mpack_done_str(reader);
811 if (mpack_reader_error(reader) != mpack_ok)
812 return count;
813
814 // find what key it matches
815 size_t i;
816 for (i = 0; i < count; ++i) {
817 const char* other = strings[i];
818 size_t otherlen = mpack_strlen(other);
819 if (keylen == otherlen && mpack_memcmp(key, other, keylen) == 0)
820 return i;
821 }
822
823 // no matches
824 return count;
825}
826
827size_t mpack_expect_key_uint(mpack_reader_t* reader, bool found[], size_t count) {
828 if (mpack_reader_error(reader) != mpack_ok)
829 return count;
830
831 if (count == 0) {
832 mpack_break("count cannot be zero; no keys are valid!");
833 mpack_reader_flag_error(reader, mpack_error_bug);
834 return count;
835 }
836 mpack_assert(found != NULL, "found cannot be NULL");
837
838 // the key is only recognized if it is an unsigned int
839 if (mpack_peek_tag(reader).type != mpack_type_uint) {
840 mpack_discard(reader);
841 return count;
842 }
843
844 // read the key
845 uint64_t value = mpack_expect_u64(reader);
846 if (mpack_reader_error(reader) != mpack_ok)
847 return count;
848
849 // unrecognized keys are fine, we just return count
850 if (value >= count)
851 return count;
852
853 // check if this key is a duplicate
854 if (found[value]) {
855 mpack_reader_flag_error(reader, mpack_error_invalid);
856 return count;
857 }
858
859 found[value] = true;
860 return (size_t)value;
861}
862
863size_t mpack_expect_key_cstr(mpack_reader_t* reader, const char* keys[], bool found[], size_t count) {
864 size_t i = mpack_expect_enum_optional(reader, keys, count);
865
866 // unrecognized keys are fine, we just return count
867 if (i == count)
868 return count;
869
870 // check if this key is a duplicate
871 mpack_assert(found != NULL, "found cannot be NULL");
872 if (found[i]) {
873 mpack_reader_flag_error(reader, mpack_error_invalid);
874 return count;
875 }
876
877 found[i] = true;
878 return i;
879}
880
881#endif
882
883MPACK_SILENCE_WARNINGS_END
884