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 | |
26 | MPACK_SILENCE_WARNINGS_BEGIN |
27 | |
28 | #if MPACK_EXPECT |
29 | |
30 | |
31 | // Helpers |
32 | |
33 | MPACK_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 |
45 | MPACK_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 | |
56 | MPACK_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 | |
68 | MPACK_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 | |
76 | uint8_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 | |
89 | uint16_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 | |
102 | uint32_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 | |
115 | uint64_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 | |
127 | int8_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 | |
140 | int16_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 | |
153 | int32_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 | |
166 | int64_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 |
179 | float 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 |
202 | double 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 |
218 | float 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 |
228 | double 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 |
240 | uint32_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 |
250 | uint64_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 | |
286 | uint8_t mpack_expect_u8_range(mpack_reader_t* reader, uint8_t min_value, uint8_t max_value) {MPACK_EXPECT_RANGE_IMPL(u8, uint8_t)} |
287 | uint16_t mpack_expect_u16_range(mpack_reader_t* reader, uint16_t min_value, uint16_t max_value) {MPACK_EXPECT_RANGE_IMPL(u16, uint16_t)} |
288 | uint32_t mpack_expect_u32_range(mpack_reader_t* reader, uint32_t min_value, uint32_t max_value) {MPACK_EXPECT_RANGE_IMPL(u32, uint32_t)} |
289 | uint64_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 | |
291 | int8_t mpack_expect_i8_range(mpack_reader_t* reader, int8_t min_value, int8_t max_value) {MPACK_EXPECT_RANGE_IMPL(i8, int8_t)} |
292 | int16_t mpack_expect_i16_range(mpack_reader_t* reader, int16_t min_value, int16_t max_value) {MPACK_EXPECT_RANGE_IMPL(i16, int16_t)} |
293 | int32_t mpack_expect_i32_range(mpack_reader_t* reader, int32_t min_value, int32_t max_value) {MPACK_EXPECT_RANGE_IMPL(i32, int32_t)} |
294 | int64_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 |
297 | float 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 |
300 | double mpack_expect_double_range(mpack_reader_t* reader, double min_value, double max_value) {MPACK_EXPECT_RANGE_IMPL(double, double)} |
301 | #endif |
302 | |
303 | uint32_t mpack_expect_map_range(mpack_reader_t* reader, uint32_t min_value, uint32_t max_value) {MPACK_EXPECT_RANGE_IMPL(map, uint32_t)} |
304 | uint32_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 | |
309 | void 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 | |
314 | void 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 | |
322 | void 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 | |
327 | bool 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 | |
334 | void 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 | |
339 | void 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 |
345 | mpack_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 | |
361 | int64_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 | |
369 | uint32_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 | |
377 | void 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 | |
382 | bool 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 | |
399 | bool 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 | |
411 | uint32_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 | |
419 | void 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 | |
424 | bool 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 | |
441 | bool 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 |
454 | void* 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 | |
491 | uint32_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 | |
522 | size_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 | |
542 | size_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 | |
555 | uint32_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 | |
563 | size_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 | |
580 | void 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 |
588 | uint32_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 | |
599 | size_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 | |
620 | void 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 | |
626 | void 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 |
633 | static 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 | |
661 | char* 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 | |
674 | char* 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 | |
688 | void 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 | |
710 | void 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 |
717 | char* 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) |
743 | char* 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 | |
771 | size_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 | |
794 | size_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 | |
827 | size_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 | |
863 | size_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 | |
883 | MPACK_SILENCE_WARNINGS_END |
884 | |