You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6440 lines
211 KiB

  1. /**
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2015-2018 Nicholas Fraser
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. *
  24. */
  25. /*
  26. * This is the MPack 1.0 amalgamation package.
  27. *
  28. * http://github.com/ludocode/mpack
  29. */
  30. #define MPACK_INTERNAL 1
  31. #define MPACK_EMIT_INLINE_DEFS 1
  32. #include "mpack.h"
  33. /* mpack/mpack-platform.c.c */
  34. // We define MPACK_EMIT_INLINE_DEFS and include mpack.h to emit
  35. // standalone definitions of all (non-static) inline functions in MPack.
  36. #define MPACK_INTERNAL 1
  37. #define MPACK_EMIT_INLINE_DEFS 1
  38. /* #include "mpack-platform.h" */
  39. /* #include "mpack.h" */
  40. #if MPACK_DEBUG && MPACK_STDIO
  41. #include <stdarg.h>
  42. #endif
  43. #if MPACK_DEBUG
  44. #if MPACK_STDIO
  45. void mpack_assert_fail_format(const char* format, ...) {
  46. char buffer[512];
  47. va_list args;
  48. va_start(args, format);
  49. vsnprintf(buffer, sizeof(buffer), format, args);
  50. va_end(args);
  51. buffer[sizeof(buffer) - 1] = 0;
  52. mpack_assert_fail_wrapper(buffer);
  53. }
  54. void mpack_break_hit_format(const char* format, ...) {
  55. char buffer[512];
  56. va_list args;
  57. va_start(args, format);
  58. vsnprintf(buffer, sizeof(buffer), format, args);
  59. va_end(args);
  60. buffer[sizeof(buffer) - 1] = 0;
  61. mpack_break_hit(buffer);
  62. }
  63. #endif
  64. #if !MPACK_CUSTOM_ASSERT
  65. void mpack_assert_fail(const char* message) {
  66. MPACK_UNUSED(message);
  67. #if MPACK_STDIO
  68. fprintf(stderr, "%s\n", message);
  69. #endif
  70. }
  71. #endif
  72. // We split the assert failure from the wrapper so that a
  73. // custom assert function can return.
  74. void mpack_assert_fail_wrapper(const char* message) {
  75. #ifdef MPACK_GCOV
  76. // gcov marks even __builtin_unreachable() as an uncovered line. this
  77. // silences it.
  78. (mpack_assert_fail(message), __builtin_unreachable());
  79. #else
  80. mpack_assert_fail(message);
  81. // mpack_assert_fail() is not supposed to return. in case it does, we
  82. // abort.
  83. #if !MPACK_NO_BUILTINS
  84. #if defined(__GNUC__) || defined(__clang__)
  85. __builtin_trap();
  86. #elif defined(WIN32)
  87. __debugbreak();
  88. #endif
  89. #endif
  90. #if (defined(__GNUC__) || defined(__clang__)) && !MPACK_NO_BUILTINS
  91. __builtin_abort();
  92. #elif MPACK_STDLIB
  93. abort();
  94. #endif
  95. MPACK_UNREACHABLE;
  96. #endif
  97. }
  98. #if !MPACK_CUSTOM_BREAK
  99. // If we have a custom assert handler, break wraps it by default.
  100. // This allows users of MPack to only implement mpack_assert_fail() without
  101. // having to worry about the difference between assert and break.
  102. //
  103. // MPACK_CUSTOM_BREAK is available to define a separate break handler
  104. // (which is needed by the unit test suite), but this is not offered in
  105. // mpack-config.h for simplicity.
  106. #if MPACK_CUSTOM_ASSERT
  107. void mpack_break_hit(const char* message) {
  108. mpack_assert_fail_wrapper(message);
  109. }
  110. #else
  111. void mpack_break_hit(const char* message) {
  112. MPACK_UNUSED(message);
  113. #if MPACK_STDIO
  114. fprintf(stderr, "%s\n", message);
  115. #endif
  116. #if defined(__GNUC__) || defined(__clang__) && !MPACK_NO_BUILTINS
  117. __builtin_trap();
  118. #elif defined(WIN32) && !MPACK_NO_BUILTINS
  119. __debugbreak();
  120. #elif MPACK_STDLIB
  121. abort();
  122. #endif
  123. }
  124. #endif
  125. #endif
  126. #endif
  127. // The below are adapted from the C wikibook:
  128. // https://en.wikibooks.org/wiki/C_Programming/Strings
  129. #ifndef mpack_memcmp
  130. int mpack_memcmp(const void* s1, const void* s2, size_t n) {
  131. const unsigned char *us1 = (const unsigned char *) s1;
  132. const unsigned char *us2 = (const unsigned char *) s2;
  133. while (n-- != 0) {
  134. if (*us1 != *us2)
  135. return (*us1 < *us2) ? -1 : +1;
  136. us1++;
  137. us2++;
  138. }
  139. return 0;
  140. }
  141. #endif
  142. #ifndef mpack_memcpy
  143. void* mpack_memcpy(void* MPACK_RESTRICT s1, const void* MPACK_RESTRICT s2, size_t n) {
  144. char* MPACK_RESTRICT dst = (char *)s1;
  145. const char* MPACK_RESTRICT src = (const char *)s2;
  146. while (n-- != 0)
  147. *dst++ = *src++;
  148. return s1;
  149. }
  150. #endif
  151. #ifndef mpack_memmove
  152. void* mpack_memmove(void* s1, const void* s2, size_t n) {
  153. char *p1 = (char *)s1;
  154. const char *p2 = (const char *)s2;
  155. if (p2 < p1 && p1 < p2 + n) {
  156. p2 += n;
  157. p1 += n;
  158. while (n-- != 0)
  159. *--p1 = *--p2;
  160. } else
  161. while (n-- != 0)
  162. *p1++ = *p2++;
  163. return s1;
  164. }
  165. #endif
  166. #ifndef mpack_memset
  167. void* mpack_memset(void* s, int c, size_t n) {
  168. unsigned char *us = (unsigned char *)s;
  169. unsigned char uc = (unsigned char)c;
  170. while (n-- != 0)
  171. *us++ = uc;
  172. return s;
  173. }
  174. #endif
  175. #ifndef mpack_strlen
  176. size_t mpack_strlen(const char* s) {
  177. const char* p = s;
  178. while (*p != '\0')
  179. p++;
  180. return (size_t)(p - s);
  181. }
  182. #endif
  183. #if defined(MPACK_MALLOC) && !defined(MPACK_REALLOC)
  184. void* mpack_realloc(void* old_ptr, size_t used_size, size_t new_size) {
  185. if (new_size == 0) {
  186. if (old_ptr)
  187. MPACK_FREE(old_ptr);
  188. return NULL;
  189. }
  190. void* new_ptr = MPACK_MALLOC(new_size);
  191. if (new_ptr == NULL)
  192. return NULL;
  193. mpack_memcpy(new_ptr, old_ptr, used_size);
  194. MPACK_FREE(old_ptr);
  195. return new_ptr;
  196. }
  197. #endif
  198. /* mpack/mpack-common.c.c */
  199. #define MPACK_INTERNAL 1
  200. /* #include "mpack-common.h" */
  201. #if MPACK_DEBUG && MPACK_STDIO
  202. #include <stdarg.h>
  203. #endif
  204. const char* mpack_error_to_string(mpack_error_t error) {
  205. #if MPACK_STRINGS
  206. switch (error) {
  207. #define MPACK_ERROR_STRING_CASE(e) case e: return #e
  208. MPACK_ERROR_STRING_CASE(mpack_ok);
  209. MPACK_ERROR_STRING_CASE(mpack_error_io);
  210. MPACK_ERROR_STRING_CASE(mpack_error_invalid);
  211. MPACK_ERROR_STRING_CASE(mpack_error_unsupported);
  212. MPACK_ERROR_STRING_CASE(mpack_error_type);
  213. MPACK_ERROR_STRING_CASE(mpack_error_too_big);
  214. MPACK_ERROR_STRING_CASE(mpack_error_memory);
  215. MPACK_ERROR_STRING_CASE(mpack_error_bug);
  216. MPACK_ERROR_STRING_CASE(mpack_error_data);
  217. MPACK_ERROR_STRING_CASE(mpack_error_eof);
  218. #undef MPACK_ERROR_STRING_CASE
  219. }
  220. mpack_assert(0, "unrecognized error %i", (int)error);
  221. return "(unknown mpack_error_t)";
  222. #else
  223. MPACK_UNUSED(error);
  224. return "";
  225. #endif
  226. }
  227. const char* mpack_type_to_string(mpack_type_t type) {
  228. #if MPACK_STRINGS
  229. switch (type) {
  230. #define MPACK_TYPE_STRING_CASE(e) case e: return #e
  231. MPACK_TYPE_STRING_CASE(mpack_type_missing);
  232. MPACK_TYPE_STRING_CASE(mpack_type_nil);
  233. MPACK_TYPE_STRING_CASE(mpack_type_bool);
  234. MPACK_TYPE_STRING_CASE(mpack_type_float);
  235. MPACK_TYPE_STRING_CASE(mpack_type_double);
  236. MPACK_TYPE_STRING_CASE(mpack_type_int);
  237. MPACK_TYPE_STRING_CASE(mpack_type_uint);
  238. MPACK_TYPE_STRING_CASE(mpack_type_str);
  239. MPACK_TYPE_STRING_CASE(mpack_type_bin);
  240. MPACK_TYPE_STRING_CASE(mpack_type_array);
  241. MPACK_TYPE_STRING_CASE(mpack_type_map);
  242. #if MPACK_EXTENSIONS
  243. MPACK_TYPE_STRING_CASE(mpack_type_ext);
  244. #endif
  245. #undef MPACK_TYPE_STRING_CASE
  246. }
  247. mpack_assert(0, "unrecognized type %i", (int)type);
  248. return "(unknown mpack_type_t)";
  249. #else
  250. MPACK_UNUSED(type);
  251. return "";
  252. #endif
  253. }
  254. int mpack_tag_cmp(mpack_tag_t left, mpack_tag_t right) {
  255. // positive numbers may be stored as int; convert to uint
  256. if (left.type == mpack_type_int && left.v.i >= 0) {
  257. left.type = mpack_type_uint;
  258. left.v.u = (uint64_t)left.v.i;
  259. }
  260. if (right.type == mpack_type_int && right.v.i >= 0) {
  261. right.type = mpack_type_uint;
  262. right.v.u = (uint64_t)right.v.i;
  263. }
  264. if (left.type != right.type)
  265. return ((int)left.type < (int)right.type) ? -1 : 1;
  266. switch (left.type) {
  267. case mpack_type_missing: // fallthrough
  268. case mpack_type_nil:
  269. return 0;
  270. case mpack_type_bool:
  271. return (int)left.v.b - (int)right.v.b;
  272. case mpack_type_int:
  273. if (left.v.i == right.v.i)
  274. return 0;
  275. return (left.v.i < right.v.i) ? -1 : 1;
  276. case mpack_type_uint:
  277. if (left.v.u == right.v.u)
  278. return 0;
  279. return (left.v.u < right.v.u) ? -1 : 1;
  280. case mpack_type_array:
  281. case mpack_type_map:
  282. if (left.v.n == right.v.n)
  283. return 0;
  284. return (left.v.n < right.v.n) ? -1 : 1;
  285. case mpack_type_str:
  286. case mpack_type_bin:
  287. if (left.v.l == right.v.l)
  288. return 0;
  289. return (left.v.l < right.v.l) ? -1 : 1;
  290. #if MPACK_EXTENSIONS
  291. case mpack_type_ext:
  292. if (left.exttype == right.exttype) {
  293. if (left.v.l == right.v.l)
  294. return 0;
  295. return (left.v.l < right.v.l) ? -1 : 1;
  296. }
  297. return (int)left.exttype - (int)right.exttype;
  298. #endif
  299. // floats should not normally be compared for equality. we compare
  300. // with memcmp() to silence compiler warnings, but this will return
  301. // equal if both are NaNs with the same representation (though we may
  302. // want this, for instance if you are for some bizarre reason using
  303. // floats as map keys.) i'm not sure what the right thing to
  304. // do is here. check for NaN first? always return false if the type
  305. // is float? use operator== and pragmas to silence compiler warning?
  306. // please send me your suggestions.
  307. // note also that we don't convert floats to doubles, so when this is
  308. // used for ordering purposes, all floats are ordered before all
  309. // doubles.
  310. case mpack_type_float:
  311. return mpack_memcmp(&left.v.f, &right.v.f, sizeof(left.v.f));
  312. case mpack_type_double:
  313. return mpack_memcmp(&left.v.d, &right.v.d, sizeof(left.v.d));
  314. }
  315. mpack_assert(0, "unrecognized type %i", (int)left.type);
  316. return false;
  317. }
  318. #if MPACK_DEBUG && MPACK_STDIO
  319. static char mpack_hex_char(uint8_t hex_value) {
  320. return (hex_value < 10) ? (char)('0' + hex_value) : (char)('a' + (hex_value - 10));
  321. }
  322. static void mpack_tag_debug_complete_bin_ext(mpack_tag_t tag, size_t string_length, char* buffer, size_t buffer_size,
  323. const char* prefix, size_t prefix_size)
  324. {
  325. // If at any point in this function we run out of space in the buffer, we
  326. // bail out. The outer tag print wrapper will make sure we have a
  327. // null-terminator.
  328. if (string_length == 0 || string_length >= buffer_size)
  329. return;
  330. buffer += string_length;
  331. buffer_size -= string_length;
  332. size_t total = mpack_tag_bytes(&tag);
  333. if (total == 0) {
  334. strncpy(buffer, ">", buffer_size);
  335. return;
  336. }
  337. strncpy(buffer, ": ", buffer_size);
  338. if (buffer_size < 2)
  339. return;
  340. buffer += 2;
  341. buffer_size -= 2;
  342. size_t hex_bytes = 0;
  343. for (size_t i = 0; i < MPACK_PRINT_BYTE_COUNT && i < prefix_size && buffer_size > 2; ++i) {
  344. uint8_t byte = (uint8_t)prefix[i];
  345. buffer[0] = mpack_hex_char((uint8_t)(byte >> 4));
  346. buffer[1] = mpack_hex_char((uint8_t)(byte & 0xfu));
  347. buffer += 2;
  348. buffer_size -= 2;
  349. ++hex_bytes;
  350. }
  351. if (buffer_size != 0)
  352. mpack_snprintf(buffer, buffer_size, "%s>", (total > hex_bytes) ? "..." : "");
  353. }
  354. static void mpack_tag_debug_pseudo_json_bin(mpack_tag_t tag, char* buffer, size_t buffer_size,
  355. const char* prefix, size_t prefix_size)
  356. {
  357. mpack_assert(mpack_tag_type(&tag) == mpack_type_bin);
  358. size_t length = (size_t)mpack_snprintf(buffer, buffer_size, "<binary data of length %u", tag.v.l);
  359. mpack_tag_debug_complete_bin_ext(tag, length, buffer, buffer_size, prefix, prefix_size);
  360. }
  361. #if MPACK_EXTENSIONS
  362. static void mpack_tag_debug_pseudo_json_ext(mpack_tag_t tag, char* buffer, size_t buffer_size,
  363. const char* prefix, size_t prefix_size)
  364. {
  365. mpack_assert(mpack_tag_type(&tag) == mpack_type_ext);
  366. size_t length = (size_t)mpack_snprintf(buffer, buffer_size, "<ext data of type %i and length %u",
  367. mpack_tag_ext_exttype(&tag), mpack_tag_ext_length(&tag));
  368. mpack_tag_debug_complete_bin_ext(tag, length, buffer, buffer_size, prefix, prefix_size);
  369. }
  370. #endif
  371. static void mpack_tag_debug_pseudo_json_impl(mpack_tag_t tag, char* buffer, size_t buffer_size,
  372. const char* prefix, size_t prefix_size)
  373. {
  374. switch (tag.type) {
  375. case mpack_type_missing:
  376. mpack_snprintf(buffer, buffer_size, "<missing!>");
  377. return;
  378. case mpack_type_nil:
  379. mpack_snprintf(buffer, buffer_size, "null");
  380. return;
  381. case mpack_type_bool:
  382. mpack_snprintf(buffer, buffer_size, tag.v.b ? "true" : "false");
  383. return;
  384. case mpack_type_int:
  385. mpack_snprintf(buffer, buffer_size, "%" PRIi64, tag.v.i);
  386. return;
  387. case mpack_type_uint:
  388. mpack_snprintf(buffer, buffer_size, "%" PRIu64, tag.v.u);
  389. return;
  390. case mpack_type_float:
  391. mpack_snprintf(buffer, buffer_size, "%f", tag.v.f);
  392. return;
  393. case mpack_type_double:
  394. mpack_snprintf(buffer, buffer_size, "%f", tag.v.d);
  395. return;
  396. case mpack_type_str:
  397. mpack_snprintf(buffer, buffer_size, "<string of %u bytes>", tag.v.l);
  398. return;
  399. case mpack_type_bin:
  400. mpack_tag_debug_pseudo_json_bin(tag, buffer, buffer_size, prefix, prefix_size);
  401. return;
  402. #if MPACK_EXTENSIONS
  403. case mpack_type_ext:
  404. mpack_tag_debug_pseudo_json_ext(tag, buffer, buffer_size, prefix, prefix_size);
  405. return;
  406. #endif
  407. case mpack_type_array:
  408. mpack_snprintf(buffer, buffer_size, "<array of %u elements>", tag.v.n);
  409. return;
  410. case mpack_type_map:
  411. mpack_snprintf(buffer, buffer_size, "<map of %u key-value pairs>", tag.v.n);
  412. return;
  413. }
  414. mpack_snprintf(buffer, buffer_size, "<unknown!>");
  415. }
  416. void mpack_tag_debug_pseudo_json(mpack_tag_t tag, char* buffer, size_t buffer_size,
  417. const char* prefix, size_t prefix_size)
  418. {
  419. mpack_assert(buffer_size > 0, "buffer size cannot be zero!");
  420. buffer[0] = 0;
  421. mpack_tag_debug_pseudo_json_impl(tag, buffer, buffer_size, prefix, prefix_size);
  422. // We always null-terminate the buffer manually just in case the snprintf()
  423. // function doesn't null-terminate when the string doesn't fit.
  424. buffer[buffer_size - 1] = 0;
  425. }
  426. static void mpack_tag_debug_describe_impl(mpack_tag_t tag, char* buffer, size_t buffer_size) {
  427. switch (tag.type) {
  428. case mpack_type_missing:
  429. mpack_snprintf(buffer, buffer_size, "missing");
  430. return;
  431. case mpack_type_nil:
  432. mpack_snprintf(buffer, buffer_size, "nil");
  433. return;
  434. case mpack_type_bool:
  435. mpack_snprintf(buffer, buffer_size, tag.v.b ? "true" : "false");
  436. return;
  437. case mpack_type_int:
  438. mpack_snprintf(buffer, buffer_size, "int %" PRIi64, tag.v.i);
  439. return;
  440. case mpack_type_uint:
  441. mpack_snprintf(buffer, buffer_size, "uint %" PRIu64, tag.v.u);
  442. return;
  443. case mpack_type_float:
  444. mpack_snprintf(buffer, buffer_size, "float %f", tag.v.f);
  445. return;
  446. case mpack_type_double:
  447. mpack_snprintf(buffer, buffer_size, "double %f", tag.v.d);
  448. return;
  449. case mpack_type_str:
  450. mpack_snprintf(buffer, buffer_size, "str of %u bytes", tag.v.l);
  451. return;
  452. case mpack_type_bin:
  453. mpack_snprintf(buffer, buffer_size, "bin of %u bytes", tag.v.l);
  454. return;
  455. #if MPACK_EXTENSIONS
  456. case mpack_type_ext:
  457. mpack_snprintf(buffer, buffer_size, "ext of type %i, %u bytes",
  458. mpack_tag_ext_exttype(&tag), mpack_tag_ext_length(&tag));
  459. return;
  460. #endif
  461. case mpack_type_array:
  462. mpack_snprintf(buffer, buffer_size, "array of %u elements", tag.v.n);
  463. return;
  464. case mpack_type_map:
  465. mpack_snprintf(buffer, buffer_size, "map of %u key-value pairs", tag.v.n);
  466. return;
  467. }
  468. mpack_snprintf(buffer, buffer_size, "unknown!");
  469. }
  470. void mpack_tag_debug_describe(mpack_tag_t tag, char* buffer, size_t buffer_size) {
  471. mpack_assert(buffer_size > 0, "buffer size cannot be zero!");
  472. buffer[0] = 0;
  473. mpack_tag_debug_describe_impl(tag, buffer, buffer_size);
  474. // We always null-terminate the buffer manually just in case the snprintf()
  475. // function doesn't null-terminate when the string doesn't fit.
  476. buffer[buffer_size - 1] = 0;
  477. }
  478. #endif
  479. #if MPACK_READ_TRACKING || MPACK_WRITE_TRACKING
  480. #ifndef MPACK_TRACKING_INITIAL_CAPACITY
  481. // seems like a reasonable number. we grow by doubling, and it only
  482. // needs to be as long as the maximum depth of the message.
  483. #define MPACK_TRACKING_INITIAL_CAPACITY 8
  484. #endif
  485. mpack_error_t mpack_track_init(mpack_track_t* track) {
  486. track->count = 0;
  487. track->capacity = MPACK_TRACKING_INITIAL_CAPACITY;
  488. track->elements = (mpack_track_element_t*)MPACK_MALLOC(sizeof(mpack_track_element_t) * track->capacity);
  489. if (track->elements == NULL)
  490. return mpack_error_memory;
  491. return mpack_ok;
  492. }
  493. mpack_error_t mpack_track_grow(mpack_track_t* track) {
  494. mpack_assert(track->elements, "null track elements!");
  495. mpack_assert(track->count == track->capacity, "incorrect growing?");
  496. size_t new_capacity = track->capacity * 2;
  497. mpack_track_element_t* new_elements = (mpack_track_element_t*)mpack_realloc(track->elements,
  498. sizeof(mpack_track_element_t) * track->count, sizeof(mpack_track_element_t) * new_capacity);
  499. if (new_elements == NULL)
  500. return mpack_error_memory;
  501. track->elements = new_elements;
  502. track->capacity = new_capacity;
  503. return mpack_ok;
  504. }
  505. mpack_error_t mpack_track_push(mpack_track_t* track, mpack_type_t type, uint64_t count) {
  506. mpack_assert(track->elements, "null track elements!");
  507. mpack_log("track pushing %s count %i\n", mpack_type_to_string(type), (int)count);
  508. // maps have twice the number of elements (key/value pairs)
  509. if (type == mpack_type_map)
  510. count *= 2;
  511. // grow if needed
  512. if (track->count == track->capacity) {
  513. mpack_error_t error = mpack_track_grow(track);
  514. if (error != mpack_ok)
  515. return error;
  516. }
  517. // insert new track
  518. track->elements[track->count].type = type;
  519. track->elements[track->count].left = count;
  520. ++track->count;
  521. return mpack_ok;
  522. }
  523. mpack_error_t mpack_track_pop(mpack_track_t* track, mpack_type_t type) {
  524. mpack_assert(track->elements, "null track elements!");
  525. mpack_log("track popping %s\n", mpack_type_to_string(type));
  526. if (track->count == 0) {
  527. mpack_break("attempting to close a %s but nothing was opened!", mpack_type_to_string(type));
  528. return mpack_error_bug;
  529. }
  530. mpack_track_element_t* element = &track->elements[track->count - 1];
  531. if (element->type != type) {
  532. mpack_break("attempting to close a %s but the open element is a %s!",
  533. mpack_type_to_string(type), mpack_type_to_string(element->type));
  534. return mpack_error_bug;
  535. }
  536. if (element->left != 0) {
  537. mpack_break("attempting to close a %s but there are %" PRIu64 " %s left",
  538. mpack_type_to_string(type), element->left,
  539. (type == mpack_type_map || type == mpack_type_array) ? "elements" : "bytes");
  540. return mpack_error_bug;
  541. }
  542. --track->count;
  543. return mpack_ok;
  544. }
  545. mpack_error_t mpack_track_peek_element(mpack_track_t* track, bool read) {
  546. MPACK_UNUSED(read);
  547. mpack_assert(track->elements, "null track elements!");
  548. // if there are no open elements, that's fine, we can read/write elements at will
  549. if (track->count == 0)
  550. return mpack_ok;
  551. mpack_track_element_t* element = &track->elements[track->count - 1];
  552. if (element->type != mpack_type_map && element->type != mpack_type_array) {
  553. mpack_break("elements cannot be %s within an %s", read ? "read" : "written",
  554. mpack_type_to_string(element->type));
  555. return mpack_error_bug;
  556. }
  557. if (element->left == 0) {
  558. mpack_break("too many elements %s for %s", read ? "read" : "written",
  559. mpack_type_to_string(element->type));
  560. return mpack_error_bug;
  561. }
  562. return mpack_ok;
  563. }
  564. mpack_error_t mpack_track_element(mpack_track_t* track, bool read) {
  565. mpack_error_t error = mpack_track_peek_element(track, read);
  566. if (track->count > 0 && error == mpack_ok)
  567. --track->elements[track->count - 1].left;
  568. return error;
  569. }
  570. mpack_error_t mpack_track_bytes(mpack_track_t* track, bool read, uint64_t count) {
  571. MPACK_UNUSED(read);
  572. mpack_assert(track->elements, "null track elements!");
  573. if (track->count == 0) {
  574. mpack_break("bytes cannot be %s with no open bin, str or ext", read ? "read" : "written");
  575. return mpack_error_bug;
  576. }
  577. mpack_track_element_t* element = &track->elements[track->count - 1];
  578. if (element->type == mpack_type_map || element->type == mpack_type_array) {
  579. mpack_break("bytes cannot be %s within an %s", read ? "read" : "written",
  580. mpack_type_to_string(element->type));
  581. return mpack_error_bug;
  582. }
  583. if (element->left < count) {
  584. mpack_break("too many bytes %s for %s", read ? "read" : "written",
  585. mpack_type_to_string(element->type));
  586. return mpack_error_bug;
  587. }
  588. element->left -= count;
  589. return mpack_ok;
  590. }
  591. mpack_error_t mpack_track_str_bytes_all(mpack_track_t* track, bool read, uint64_t count) {
  592. mpack_error_t error = mpack_track_bytes(track, read, count);
  593. if (error != mpack_ok)
  594. return error;
  595. mpack_track_element_t* element = &track->elements[track->count - 1];
  596. if (element->type != mpack_type_str) {
  597. mpack_break("the open type must be a string, not a %s", mpack_type_to_string(element->type));
  598. return mpack_error_bug;
  599. }
  600. if (element->left != 0) {
  601. mpack_break("not all bytes were read; the wrong byte count was requested for a string read.");
  602. return mpack_error_bug;
  603. }
  604. return mpack_ok;
  605. }
  606. mpack_error_t mpack_track_check_empty(mpack_track_t* track) {
  607. if (track->count != 0) {
  608. mpack_break("unclosed %s", mpack_type_to_string(track->elements[0].type));
  609. return mpack_error_bug;
  610. }
  611. return mpack_ok;
  612. }
  613. mpack_error_t mpack_track_destroy(mpack_track_t* track, bool cancel) {
  614. mpack_error_t error = cancel ? mpack_ok : mpack_track_check_empty(track);
  615. if (track->elements) {
  616. MPACK_FREE(track->elements);
  617. track->elements = NULL;
  618. }
  619. return error;
  620. }
  621. #endif
  622. static bool mpack_utf8_check_impl(const uint8_t* str, size_t count, bool allow_null) {
  623. while (count > 0) {
  624. uint8_t lead = str[0];
  625. // NUL
  626. if (!allow_null && lead == '\0') // we don't allow NUL bytes in MPack C-strings
  627. return false;
  628. // ASCII
  629. if (lead <= 0x7F) {
  630. ++str;
  631. --count;
  632. // 2-byte sequence
  633. } else if ((lead & 0xE0) == 0xC0) {
  634. if (count < 2) // truncated sequence
  635. return false;
  636. uint8_t cont = str[1];
  637. if ((cont & 0xC0) != 0x80) // not a continuation byte
  638. return false;
  639. str += 2;
  640. count -= 2;
  641. uint32_t z = ((uint32_t)(lead & ~0xE0) << 6) |
  642. (uint32_t)(cont & ~0xC0);
  643. if (z < 0x80) // overlong sequence
  644. return false;
  645. // 3-byte sequence
  646. } else if ((lead & 0xF0) == 0xE0) {
  647. if (count < 3) // truncated sequence
  648. return false;
  649. uint8_t cont1 = str[1];
  650. if ((cont1 & 0xC0) != 0x80) // not a continuation byte
  651. return false;
  652. uint8_t cont2 = str[2];
  653. if ((cont2 & 0xC0) != 0x80) // not a continuation byte
  654. return false;
  655. str += 3;
  656. count -= 3;
  657. uint32_t z = ((uint32_t)(lead & ~0xF0) << 12) |
  658. ((uint32_t)(cont1 & ~0xC0) << 6) |
  659. (uint32_t)(cont2 & ~0xC0);
  660. if (z < 0x800) // overlong sequence
  661. return false;
  662. if (z >= 0xD800 && z <= 0xDFFF) // surrogate
  663. return false;
  664. // 4-byte sequence
  665. } else if ((lead & 0xF8) == 0xF0) {
  666. if (count < 4) // truncated sequence
  667. return false;
  668. uint8_t cont1 = str[1];
  669. if ((cont1 & 0xC0) != 0x80) // not a continuation byte
  670. return false;
  671. uint8_t cont2 = str[2];
  672. if ((cont2 & 0xC0) != 0x80) // not a continuation byte
  673. return false;
  674. uint8_t cont3 = str[3];
  675. if ((cont3 & 0xC0) != 0x80) // not a continuation byte
  676. return false;
  677. str += 4;
  678. count -= 4;
  679. uint32_t z = ((uint32_t)(lead & ~0xF8) << 18) |
  680. ((uint32_t)(cont1 & ~0xC0) << 12) |
  681. ((uint32_t)(cont2 & ~0xC0) << 6) |
  682. (uint32_t)(cont3 & ~0xC0);
  683. if (z < 0x10000) // overlong sequence
  684. return false;
  685. if (z > 0x10FFFF) // codepoint limit
  686. return false;
  687. } else {
  688. return false; // continuation byte without a lead, or lead for a 5-byte sequence or longer
  689. }
  690. }
  691. return true;
  692. }
  693. bool mpack_utf8_check(const char* str, size_t bytes) {
  694. return mpack_utf8_check_impl((const uint8_t*)str, bytes, true);
  695. }
  696. bool mpack_utf8_check_no_null(const char* str, size_t bytes) {
  697. return mpack_utf8_check_impl((const uint8_t*)str, bytes, false);
  698. }
  699. bool mpack_str_check_no_null(const char* str, size_t bytes) {
  700. for (size_t i = 0; i < bytes; ++i)
  701. if (str[i] == '\0')
  702. return false;
  703. return true;
  704. }
  705. #if MPACK_DEBUG && MPACK_STDIO
  706. void mpack_print_append(mpack_print_t* print, const char* data, size_t count) {
  707. // copy whatever fits into the buffer
  708. size_t copy = print->size - print->count;
  709. if (copy > count)
  710. copy = count;
  711. mpack_memcpy(print->buffer + print->count, data, copy);
  712. print->count += copy;
  713. data += copy;
  714. count -= copy;
  715. // if we don't need to flush or can't flush there's nothing else to do
  716. if (count == 0 || print->callback == NULL)
  717. return;
  718. // flush the buffer
  719. print->callback(print->context, print->buffer, print->count);
  720. if (count > print->size / 2) {
  721. // flush the rest of the data
  722. print->count = 0;
  723. print->callback(print->context, data, count);
  724. } else {
  725. // copy the rest of the data into the buffer
  726. mpack_memcpy(print->buffer, data, count);
  727. print->count = count;
  728. }
  729. }
  730. void mpack_print_flush(mpack_print_t* print) {
  731. if (print->count > 0 && print->callback != NULL) {
  732. print->callback(print->context, print->buffer, print->count);
  733. print->count = 0;
  734. }
  735. }
  736. void mpack_print_file_callback(void* context, const char* data, size_t count) {
  737. FILE* file = (FILE*)context;
  738. fwrite(data, 1, count, file);
  739. }
  740. #endif
  741. /* mpack/mpack-writer.c.c */
  742. #define MPACK_INTERNAL 1
  743. /* #include "mpack-writer.h" */
  744. #if MPACK_WRITER
  745. #if MPACK_WRITE_TRACKING
  746. static void mpack_writer_flag_if_error(mpack_writer_t* writer, mpack_error_t error) {
  747. if (error != mpack_ok)
  748. mpack_writer_flag_error(writer, error);
  749. }
  750. void mpack_writer_track_push(mpack_writer_t* writer, mpack_type_t type, uint64_t count) {
  751. if (writer->error == mpack_ok)
  752. mpack_writer_flag_if_error(writer, mpack_track_push(&writer->track, type, count));
  753. }
  754. void mpack_writer_track_pop(mpack_writer_t* writer, mpack_type_t type) {
  755. if (writer->error == mpack_ok)
  756. mpack_writer_flag_if_error(writer, mpack_track_pop(&writer->track, type));
  757. }
  758. void mpack_writer_track_element(mpack_writer_t* writer) {
  759. if (writer->error == mpack_ok)
  760. mpack_writer_flag_if_error(writer, mpack_track_element(&writer->track, false));
  761. }
  762. void mpack_writer_track_bytes(mpack_writer_t* writer, size_t count) {
  763. if (writer->error == mpack_ok)
  764. mpack_writer_flag_if_error(writer, mpack_track_bytes(&writer->track, false, count));
  765. }
  766. #endif
  767. static void mpack_writer_clear(mpack_writer_t* writer) {
  768. #if MPACK_COMPATIBILITY
  769. writer->version = mpack_version_current;
  770. #endif
  771. writer->flush = NULL;
  772. writer->error_fn = NULL;
  773. writer->teardown = NULL;
  774. writer->context = NULL;
  775. writer->buffer = NULL;
  776. writer->current = NULL;
  777. writer->end = NULL;
  778. writer->error = mpack_ok;
  779. #if MPACK_WRITE_TRACKING
  780. mpack_memset(&writer->track, 0, sizeof(writer->track));
  781. #endif
  782. }
  783. void mpack_writer_init(mpack_writer_t* writer, char* buffer, size_t size) {
  784. mpack_assert(buffer != NULL, "cannot initialize writer with empty buffer");
  785. mpack_writer_clear(writer);
  786. writer->buffer = buffer;
  787. writer->current = buffer;
  788. writer->end = writer->buffer + size;
  789. #if MPACK_WRITE_TRACKING
  790. mpack_writer_flag_if_error(writer, mpack_track_init(&writer->track));
  791. #endif
  792. mpack_log("===========================\n");
  793. mpack_log("initializing writer with buffer size %i\n", (int)size);
  794. }
  795. void mpack_writer_init_error(mpack_writer_t* writer, mpack_error_t error) {
  796. mpack_writer_clear(writer);
  797. writer->error = error;
  798. mpack_log("===========================\n");
  799. mpack_log("initializing writer in error state %i\n", (int)error);
  800. }
  801. void mpack_writer_set_flush(mpack_writer_t* writer, mpack_writer_flush_t flush) {
  802. MPACK_STATIC_ASSERT(MPACK_WRITER_MINIMUM_BUFFER_SIZE >= MPACK_MAXIMUM_TAG_SIZE,
  803. "minimum buffer size must fit any tag!");
  804. MPACK_STATIC_ASSERT(31 + MPACK_TAG_SIZE_FIXSTR >= MPACK_WRITER_MINIMUM_BUFFER_SIZE,
  805. "minimum buffer size must fit the largest possible fixstr!");
  806. if (mpack_writer_buffer_size(writer) < MPACK_WRITER_MINIMUM_BUFFER_SIZE) {
  807. mpack_break("buffer size is %i, but minimum buffer size for flush is %i",
  808. (int)mpack_writer_buffer_size(writer), MPACK_WRITER_MINIMUM_BUFFER_SIZE);
  809. mpack_writer_flag_error(writer, mpack_error_bug);
  810. return;
  811. }
  812. writer->flush = flush;
  813. }
  814. #ifdef MPACK_MALLOC
  815. typedef struct mpack_growable_writer_t {
  816. char** target_data;
  817. size_t* target_size;
  818. } mpack_growable_writer_t;
  819. static char* mpack_writer_get_reserved(mpack_writer_t* writer) {
  820. // This is in a separate function in order to avoid false strict aliasing
  821. // warnings. We aren't actually violating strict aliasing (the reserved
  822. // space is only ever dereferenced as an mpack_growable_writer_t.)
  823. return (char*)writer->reserved;
  824. }
  825. static void mpack_growable_writer_flush(mpack_writer_t* writer, const char* data, size_t count) {
  826. // This is an intrusive flush function which modifies the writer's buffer
  827. // in response to a flush instead of emptying it in order to add more
  828. // capacity for data. This removes the need to copy data from a fixed buffer
  829. // into a growable one, improving performance.
  830. //
  831. // There are three ways flush can be called:
  832. // - flushing the buffer during writing (used is zero, count is all data, data is buffer)
  833. // - flushing extra data during writing (used is all flushed data, count is extra data, data is not buffer)
  834. // - flushing during teardown (used and count are both all flushed data, data is buffer)
  835. //
  836. // In the first two cases, we grow the buffer by at least double, enough
  837. // to ensure that new data will fit. We ignore the teardown flush.
  838. if (data == writer->buffer) {
  839. // teardown, do nothing
  840. if (mpack_writer_buffer_used(writer) == count)
  841. return;
  842. // otherwise leave the data in the buffer and just grow
  843. writer->current = writer->buffer + count;
  844. count = 0;
  845. }
  846. size_t used = mpack_writer_buffer_used(writer);
  847. size_t size = mpack_writer_buffer_size(writer);
  848. mpack_log("flush size %i used %i data %p buffer %p\n",
  849. (int)count, (int)used, data, writer->buffer);
  850. mpack_assert(data == writer->buffer || used + count > size,
  851. "extra flush for %i but there is %i space left in the buffer! (%i/%i)",
  852. (int)count, (int)mpack_writer_buffer_left(writer), (int)used, (int)size);
  853. // grow to fit the data
  854. // TODO: this really needs to correctly test for overflow
  855. size_t new_size = size * 2;
  856. while (new_size < used + count)
  857. new_size *= 2;
  858. mpack_log("flush growing buffer size from %i to %i\n", (int)size, (int)new_size);
  859. // grow the buffer
  860. char* new_buffer = (char*)mpack_realloc(writer->buffer, used, new_size);
  861. if (new_buffer == NULL) {
  862. mpack_writer_flag_error(writer, mpack_error_memory);
  863. return;
  864. }
  865. writer->current = new_buffer + used;
  866. writer->buffer = new_buffer;
  867. writer->end = writer->buffer + new_size;
  868. // append the extra data
  869. if (count > 0) {
  870. mpack_memcpy(writer->current, data, count);
  871. writer->current += count;
  872. }
  873. mpack_log("new buffer %p, used %i\n", new_buffer, (int)mpack_writer_buffer_used(writer));
  874. }
  875. static void mpack_growable_writer_teardown(mpack_writer_t* writer) {
  876. mpack_growable_writer_t* growable_writer = (mpack_growable_writer_t*)mpack_writer_get_reserved(writer);
  877. if (mpack_writer_error(writer) == mpack_ok) {
  878. // shrink the buffer to an appropriate size if the data is
  879. // much smaller than the buffer
  880. if (mpack_writer_buffer_used(writer) < mpack_writer_buffer_size(writer) / 2) {
  881. size_t used = mpack_writer_buffer_used(writer);
  882. // We always return a non-null pointer that must be freed, even if
  883. // nothing was written. malloc() and realloc() do not necessarily
  884. // do this so we enforce it ourselves.
  885. size_t size = (used != 0) ? used : 1;
  886. char* buffer = (char*)mpack_realloc(writer->buffer, used, size);
  887. if (!buffer) {
  888. MPACK_FREE(writer->buffer);
  889. mpack_writer_flag_error(writer, mpack_error_memory);
  890. return;
  891. }
  892. writer->buffer = buffer;
  893. writer->end = (writer->current = writer->buffer + used);
  894. }
  895. *growable_writer->target_data = writer->buffer;
  896. *growable_writer->target_size = mpack_writer_buffer_used(writer);
  897. writer->buffer = NULL;
  898. } else if (writer->buffer) {
  899. MPACK_FREE(writer->buffer);
  900. writer->buffer = NULL;
  901. }
  902. writer->context = NULL;
  903. }
  904. void mpack_writer_init_growable(mpack_writer_t* writer, char** target_data, size_t* target_size) {
  905. mpack_assert(target_data != NULL, "cannot initialize writer without a destination for the data");
  906. mpack_assert(target_size != NULL, "cannot initialize writer without a destination for the size");
  907. *target_data = NULL;
  908. *target_size = 0;
  909. MPACK_STATIC_ASSERT(sizeof(mpack_growable_writer_t) <= sizeof(writer->reserved),
  910. "not enough reserved space for growable writer!");
  911. mpack_growable_writer_t* growable_writer = (mpack_growable_writer_t*)mpack_writer_get_reserved(writer);
  912. growable_writer->target_data = target_data;
  913. growable_writer->target_size = target_size;
  914. size_t capacity = MPACK_BUFFER_SIZE;
  915. char* buffer = (char*)MPACK_MALLOC(capacity);
  916. if (buffer == NULL) {
  917. mpack_writer_init_error(writer, mpack_error_memory);
  918. return;
  919. }
  920. mpack_writer_init(writer, buffer, capacity);
  921. mpack_writer_set_flush(writer, mpack_growable_writer_flush);
  922. mpack_writer_set_teardown(writer, mpack_growable_writer_teardown);
  923. }
  924. #endif
  925. #if MPACK_STDIO
  926. static void mpack_file_writer_flush(mpack_writer_t* writer, const char* buffer, size_t count) {
  927. FILE* file = (FILE*)writer->context;
  928. size_t written = fwrite((const void*)buffer, 1, count, file);
  929. if (written != count)
  930. mpack_writer_flag_error(writer, mpack_error_io);
  931. }
  932. static void mpack_file_writer_teardown(mpack_writer_t* writer) {
  933. MPACK_FREE(writer->buffer);
  934. writer->buffer = NULL;
  935. writer->context = NULL;
  936. }
  937. static void mpack_file_writer_teardown_close(mpack_writer_t* writer) {
  938. FILE* file = (FILE*)writer->context;
  939. if (file) {
  940. int ret = fclose(file);
  941. if (ret != 0)
  942. mpack_writer_flag_error(writer, mpack_error_io);
  943. }
  944. mpack_file_writer_teardown(writer);
  945. }
  946. void mpack_writer_init_stdfile(mpack_writer_t* writer, FILE* file, bool close_when_done) {
  947. mpack_assert(file != NULL, "file is NULL");
  948. size_t capacity = MPACK_BUFFER_SIZE;
  949. char* buffer = (char*)MPACK_MALLOC(capacity);
  950. if (buffer == NULL) {
  951. mpack_writer_init_error(writer, mpack_error_memory);
  952. if (close_when_done) {
  953. fclose(file);
  954. }
  955. return;
  956. }
  957. mpack_writer_init(writer, buffer, capacity);
  958. mpack_writer_set_context(writer, file);
  959. mpack_writer_set_flush(writer, mpack_file_writer_flush);
  960. mpack_writer_set_teardown(writer, close_when_done ?
  961. mpack_file_writer_teardown_close :
  962. mpack_file_writer_teardown);
  963. }
  964. void mpack_writer_init_filename(mpack_writer_t* writer, const char* filename) {
  965. mpack_assert(filename != NULL, "filename is NULL");
  966. FILE* file = fopen(filename, "wb");
  967. if (file == NULL) {
  968. mpack_writer_init_error(writer, mpack_error_io);
  969. return;
  970. }
  971. mpack_writer_init_stdfile(writer, file, true);
  972. }
  973. #endif
  974. void mpack_writer_flag_error(mpack_writer_t* writer, mpack_error_t error) {
  975. mpack_log("writer %p setting error %i: %s\n", writer, (int)error, mpack_error_to_string(error));
  976. if (writer->error == mpack_ok) {
  977. writer->error = error;
  978. if (writer->error_fn)
  979. writer->error_fn(writer, writer->error);
  980. }
  981. }
  982. MPACK_STATIC_INLINE void mpack_writer_flush_unchecked(mpack_writer_t* writer) {
  983. // This is a bit ugly; we reset used before calling flush so that
  984. // a flush function can distinguish between flushing the buffer
  985. // versus flushing external data. see mpack_growable_writer_flush()
  986. size_t used = mpack_writer_buffer_used(writer);
  987. writer->current = writer->buffer;
  988. writer->flush(writer, writer->buffer, used);
  989. }
  990. void mpack_writer_flush_message(mpack_writer_t* writer) {
  991. if (writer->error != mpack_ok)
  992. return;
  993. #if MPACK_WRITE_TRACKING
  994. mpack_writer_flag_if_error(writer, mpack_track_check_empty(&writer->track));
  995. if (writer->error != mpack_ok)
  996. return;
  997. #endif
  998. if (writer->flush == NULL) {
  999. mpack_break("cannot call mpack_writer_flush_message() without a flush function!");
  1000. mpack_writer_flag_error(writer, mpack_error_bug);
  1001. return;
  1002. }
  1003. if (mpack_writer_buffer_used(writer) > 0)
  1004. mpack_writer_flush_unchecked(writer);
  1005. }
  1006. // Ensures there are at least count bytes free in the buffer. This
  1007. // will flag an error if the flush function fails to make enough
  1008. // room in the buffer.
  1009. MPACK_NOINLINE static bool mpack_writer_ensure(mpack_writer_t* writer, size_t count) {
  1010. mpack_assert(count != 0, "cannot ensure zero bytes!");
  1011. mpack_assert(count <= MPACK_WRITER_MINIMUM_BUFFER_SIZE,
  1012. "cannot ensure %i bytes, this is more than the minimum buffer size %i!",
  1013. (int)count, (int)MPACK_WRITER_MINIMUM_BUFFER_SIZE);
  1014. mpack_assert(count > mpack_writer_buffer_left(writer),
  1015. "request to ensure %i bytes but there are already %i left in the buffer!",
  1016. (int)count, (int)mpack_writer_buffer_left(writer));
  1017. mpack_log("ensuring %i bytes, %i left\n", (int)count, (int)mpack_writer_buffer_left(writer));
  1018. if (mpack_writer_error(writer) != mpack_ok)
  1019. return false;
  1020. if (writer->flush == NULL) {
  1021. mpack_writer_flag_error(writer, mpack_error_too_big);
  1022. return false;
  1023. }
  1024. mpack_writer_flush_unchecked(writer);
  1025. if (mpack_writer_error(writer) != mpack_ok)
  1026. return false;
  1027. if (mpack_writer_buffer_left(writer) >= count)
  1028. return true;
  1029. mpack_writer_flag_error(writer, mpack_error_io);
  1030. return false;
  1031. }
  1032. // Writes encoded bytes to the buffer when we already know the data
  1033. // does not fit in the buffer (i.e. it straddles the edge of the
  1034. // buffer.) If there is a flush function, it is guaranteed to be
  1035. // called; otherwise mpack_error_too_big is raised.
  1036. MPACK_NOINLINE static void mpack_write_native_straddle(mpack_writer_t* writer, const char* p, size_t count) {
  1037. mpack_assert(count == 0 || p != NULL, "data pointer for %i bytes is NULL", (int)count);
  1038. if (mpack_writer_error(writer) != mpack_ok)
  1039. return;
  1040. mpack_log("big write for %i bytes from %p, %i space left in buffer\n",
  1041. (int)count, p, (int)mpack_writer_buffer_left(writer));
  1042. mpack_assert(count > mpack_writer_buffer_left(writer),
  1043. "big write requested for %i bytes, but there is %i available "
  1044. "space in buffer. should have called mpack_write_native() instead",
  1045. (int)count, (int)(mpack_writer_buffer_left(writer)));
  1046. // we'll need a flush function
  1047. if (!writer->flush) {
  1048. mpack_writer_flag_error(writer, mpack_error_too_big);
  1049. return;
  1050. }
  1051. // flush the buffer
  1052. mpack_writer_flush_unchecked(writer);
  1053. if (mpack_writer_error(writer) != mpack_ok)
  1054. return;
  1055. // note that an intrusive flush function (such as mpack_growable_writer_flush())
  1056. // may have changed size and/or reset used to a non-zero value. we treat both as
  1057. // though they may have changed, and there may still be data in the buffer.
  1058. // flush the extra data directly if it doesn't fit in the buffer
  1059. if (count > mpack_writer_buffer_left(writer)) {
  1060. writer->flush(writer, p, count);
  1061. if (mpack_writer_error(writer) != mpack_ok)
  1062. return;
  1063. } else {
  1064. mpack_memcpy(writer->current, p, count);
  1065. writer->current += count;
  1066. }
  1067. }
  1068. // Writes encoded bytes to the buffer, flushing if necessary.
  1069. MPACK_STATIC_INLINE void mpack_write_native(mpack_writer_t* writer, const char* p, size_t count) {
  1070. mpack_assert(count == 0 || p != NULL, "data pointer for %i bytes is NULL", (int)count);
  1071. if (mpack_writer_buffer_left(writer) < count) {
  1072. mpack_write_native_straddle(writer, p, count);
  1073. } else {
  1074. mpack_memcpy(writer->current, p, count);
  1075. writer->current += count;
  1076. }
  1077. }
  1078. mpack_error_t mpack_writer_destroy(mpack_writer_t* writer) {
  1079. // clean up tracking, asserting if we're not already in an error state
  1080. #if MPACK_WRITE_TRACKING
  1081. mpack_track_destroy(&writer->track, writer->error != mpack_ok);
  1082. #endif
  1083. // flush any outstanding data
  1084. if (mpack_writer_error(writer) == mpack_ok && mpack_writer_buffer_used(writer) != 0 && writer->flush != NULL) {
  1085. writer->flush(writer, writer->buffer, mpack_writer_buffer_used(writer));
  1086. writer->flush = NULL;
  1087. }
  1088. if (writer->teardown) {
  1089. writer->teardown(writer);
  1090. writer->teardown = NULL;
  1091. }
  1092. return writer->error;
  1093. }
  1094. void mpack_write_tag(mpack_writer_t* writer, mpack_tag_t value) {
  1095. switch (value.type) {
  1096. case mpack_type_missing:
  1097. mpack_break("cannot write a missing value!");
  1098. mpack_writer_flag_error(writer, mpack_error_bug);
  1099. return;
  1100. case mpack_type_nil: mpack_write_nil (writer); return;
  1101. case mpack_type_bool: mpack_write_bool (writer, value.v.b); return;
  1102. case mpack_type_float: mpack_write_float (writer, value.v.f); return;
  1103. case mpack_type_double: mpack_write_double(writer, value.v.d); return;
  1104. case mpack_type_int: mpack_write_int (writer, value.v.i); return;
  1105. case mpack_type_uint: mpack_write_uint (writer, value.v.u); return;
  1106. case mpack_type_str: mpack_start_str(writer, value.v.l); return;
  1107. case mpack_type_bin: mpack_start_bin(writer, value.v.l); return;
  1108. #if MPACK_EXTENSIONS
  1109. case mpack_type_ext:
  1110. mpack_start_ext(writer, mpack_tag_ext_exttype(&value), mpack_tag_ext_length(&value));
  1111. return;
  1112. #endif
  1113. case mpack_type_array: mpack_start_array(writer, value.v.n); return;
  1114. case mpack_type_map: mpack_start_map(writer, value.v.n); return;
  1115. }
  1116. mpack_break("unrecognized type %i", (int)value.type);
  1117. mpack_writer_flag_error(writer, mpack_error_bug);
  1118. }
  1119. MPACK_STATIC_INLINE void mpack_write_byte_element(mpack_writer_t* writer, char value) {
  1120. mpack_writer_track_element(writer);
  1121. if (MPACK_LIKELY(mpack_writer_buffer_left(writer) >= 1) || mpack_writer_ensure(writer, 1))
  1122. *(writer->current++) = value;
  1123. }
  1124. void mpack_write_nil(mpack_writer_t* writer) {
  1125. mpack_write_byte_element(writer, (char)0xc0);
  1126. }
  1127. void mpack_write_bool(mpack_writer_t* writer, bool value) {
  1128. mpack_write_byte_element(writer, (char)(0xc2 | (value ? 1 : 0)));
  1129. }
  1130. void mpack_write_true(mpack_writer_t* writer) {
  1131. mpack_write_byte_element(writer, (char)0xc3);
  1132. }
  1133. void mpack_write_false(mpack_writer_t* writer) {
  1134. mpack_write_byte_element(writer, (char)0xc2);
  1135. }
  1136. void mpack_write_object_bytes(mpack_writer_t* writer, const char* data, size_t bytes) {
  1137. mpack_writer_track_element(writer);
  1138. mpack_write_native(writer, data, bytes);
  1139. }
  1140. /*
  1141. * Encode functions
  1142. */
  1143. MPACK_STATIC_INLINE void mpack_encode_fixuint(char* p, uint8_t value) {
  1144. mpack_assert(value <= 127);
  1145. mpack_store_u8(p, value);
  1146. }
  1147. MPACK_STATIC_INLINE void mpack_encode_u8(char* p, uint8_t value) {
  1148. mpack_assert(value > 127);
  1149. mpack_store_u8(p, 0xcc);
  1150. mpack_store_u8(p + 1, value);
  1151. }
  1152. MPACK_STATIC_INLINE void mpack_encode_u16(char* p, uint16_t value) {
  1153. mpack_assert(value > UINT8_MAX);
  1154. mpack_store_u8(p, 0xcd);
  1155. mpack_store_u16(p + 1, value);
  1156. }
  1157. MPACK_STATIC_INLINE void mpack_encode_u32(char* p, uint32_t value) {
  1158. mpack_assert(value > UINT16_MAX);
  1159. mpack_store_u8(p, 0xce);
  1160. mpack_store_u32(p + 1, value);
  1161. }
  1162. MPACK_STATIC_INLINE void mpack_encode_u64(char* p, uint64_t value) {
  1163. mpack_assert(value > UINT32_MAX);
  1164. mpack_store_u8(p, 0xcf);
  1165. mpack_store_u64(p + 1, value);
  1166. }
  1167. MPACK_STATIC_INLINE void mpack_encode_fixint(char* p, int8_t value) {
  1168. // this can encode positive or negative fixints
  1169. mpack_assert(value >= -32);
  1170. mpack_store_i8(p, value);
  1171. }
  1172. MPACK_STATIC_INLINE void mpack_encode_i8(char* p, int8_t value) {
  1173. mpack_assert(value < -32);
  1174. mpack_store_u8(p, 0xd0);
  1175. mpack_store_i8(p + 1, value);
  1176. }
  1177. MPACK_STATIC_INLINE void mpack_encode_i16(char* p, int16_t value) {
  1178. mpack_assert(value < INT8_MIN);
  1179. mpack_store_u8(p, 0xd1);
  1180. mpack_store_i16(p + 1, value);
  1181. }
  1182. MPACK_STATIC_INLINE void mpack_encode_i32(char* p, int32_t value) {
  1183. mpack_assert(value < INT16_MIN);
  1184. mpack_store_u8(p, 0xd2);
  1185. mpack_store_i32(p + 1, value);
  1186. }
  1187. MPACK_STATIC_INLINE void mpack_encode_i64(char* p, int64_t value) {
  1188. mpack_assert(value < INT32_MIN);
  1189. mpack_store_u8(p, 0xd3);
  1190. mpack_store_i64(p + 1, value);
  1191. }
  1192. MPACK_STATIC_INLINE void mpack_encode_float(char* p, float value) {
  1193. mpack_store_u8(p, 0xca);
  1194. mpack_store_float(p + 1, value);
  1195. }
  1196. MPACK_STATIC_INLINE void mpack_encode_double(char* p, double value) {
  1197. mpack_store_u8(p, 0xcb);
  1198. mpack_store_double(p + 1, value);
  1199. }
  1200. MPACK_STATIC_INLINE void mpack_encode_fixarray(char* p, uint8_t count) {
  1201. mpack_assert(count <= 15);
  1202. mpack_store_u8(p, (uint8_t)(0x90 | count));
  1203. }
  1204. MPACK_STATIC_INLINE void mpack_encode_array16(char* p, uint16_t count) {
  1205. mpack_assert(count > 15);
  1206. mpack_store_u8(p, 0xdc);
  1207. mpack_store_u16(p + 1, count);
  1208. }
  1209. MPACK_STATIC_INLINE void mpack_encode_array32(char* p, uint32_t count) {
  1210. mpack_assert(count > UINT16_MAX);
  1211. mpack_store_u8(p, 0xdd);
  1212. mpack_store_u32(p + 1, count);
  1213. }
  1214. MPACK_STATIC_INLINE void mpack_encode_fixmap(char* p, uint8_t count) {
  1215. mpack_assert(count <= 15);
  1216. mpack_store_u8(p, (uint8_t)(0x80 | count));
  1217. }
  1218. MPACK_STATIC_INLINE void mpack_encode_map16(char* p, uint16_t count) {
  1219. mpack_assert(count > 15);
  1220. mpack_store_u8(p, 0xde);
  1221. mpack_store_u16(p + 1, count);
  1222. }
  1223. MPACK_STATIC_INLINE void mpack_encode_map32(char* p, uint32_t count) {
  1224. mpack_assert(count > UINT16_MAX);
  1225. mpack_store_u8(p, 0xdf);
  1226. mpack_store_u32(p + 1, count);
  1227. }
  1228. MPACK_STATIC_INLINE void mpack_encode_fixstr(char* p, uint8_t count) {
  1229. mpack_assert(count <= 31);
  1230. mpack_store_u8(p, (uint8_t)(0xa0 | count));
  1231. }
  1232. MPACK_STATIC_INLINE void mpack_encode_str8(char* p, uint8_t count) {
  1233. mpack_assert(count > 31);
  1234. mpack_store_u8(p, 0xd9);
  1235. mpack_store_u8(p + 1, count);
  1236. }
  1237. MPACK_STATIC_INLINE void mpack_encode_str16(char* p, uint16_t count) {
  1238. // we might be encoding a raw in compatibility mode, so we
  1239. // allow count to be in the range [32, UINT8_MAX].
  1240. mpack_assert(count > 31);
  1241. mpack_store_u8(p, 0xda);
  1242. mpack_store_u16(p + 1, count);
  1243. }
  1244. MPACK_STATIC_INLINE void mpack_encode_str32(char* p, uint32_t count) {
  1245. mpack_assert(count > UINT16_MAX);
  1246. mpack_store_u8(p, 0xdb);
  1247. mpack_store_u32(p + 1, count);
  1248. }
  1249. MPACK_STATIC_INLINE void mpack_encode_bin8(char* p, uint8_t count) {
  1250. mpack_store_u8(p, 0xc4);
  1251. mpack_store_u8(p + 1, count);
  1252. }
  1253. MPACK_STATIC_INLINE void mpack_encode_bin16(char* p, uint16_t count) {
  1254. mpack_assert(count > UINT8_MAX);
  1255. mpack_store_u8(p, 0xc5);
  1256. mpack_store_u16(p + 1, count);
  1257. }
  1258. MPACK_STATIC_INLINE void mpack_encode_bin32(char* p, uint32_t count) {
  1259. mpack_assert(count > UINT16_MAX);
  1260. mpack_store_u8(p, 0xc6);
  1261. mpack_store_u32(p + 1, count);
  1262. }
  1263. #if MPACK_EXTENSIONS
  1264. MPACK_STATIC_INLINE void mpack_encode_fixext1(char* p, int8_t exttype) {
  1265. mpack_store_u8(p, 0xd4);
  1266. mpack_store_i8(p + 1, exttype);
  1267. }
  1268. MPACK_STATIC_INLINE void mpack_encode_fixext2(char* p, int8_t exttype) {
  1269. mpack_store_u8(p, 0xd5);
  1270. mpack_store_i8(p + 1, exttype);
  1271. }
  1272. MPACK_STATIC_INLINE void mpack_encode_fixext4(char* p, int8_t exttype) {
  1273. mpack_store_u8(p, 0xd6);
  1274. mpack_store_i8(p + 1, exttype);
  1275. }
  1276. MPACK_STATIC_INLINE void mpack_encode_fixext8(char* p, int8_t exttype) {
  1277. mpack_store_u8(p, 0xd7);
  1278. mpack_store_i8(p + 1, exttype);
  1279. }
  1280. MPACK_STATIC_INLINE void mpack_encode_fixext16(char* p, int8_t exttype) {
  1281. mpack_store_u8(p, 0xd8);
  1282. mpack_store_i8(p + 1, exttype);
  1283. }
  1284. MPACK_STATIC_INLINE void mpack_encode_ext8(char* p, int8_t exttype, uint8_t count) {
  1285. mpack_assert(count != 1 && count != 2 && count != 4 && count != 8 && count != 16);
  1286. mpack_store_u8(p, 0xc7);
  1287. mpack_store_u8(p + 1, count);
  1288. mpack_store_i8(p + 2, exttype);
  1289. }
  1290. MPACK_STATIC_INLINE void mpack_encode_ext16(char* p, int8_t exttype, uint16_t count) {
  1291. mpack_assert(count > UINT8_MAX);
  1292. mpack_store_u8(p, 0xc8);
  1293. mpack_store_u16(p + 1, count);
  1294. mpack_store_i8(p + 3, exttype);
  1295. }
  1296. MPACK_STATIC_INLINE void mpack_encode_ext32(char* p, int8_t exttype, uint32_t count) {
  1297. mpack_assert(count > UINT16_MAX);
  1298. mpack_store_u8(p, 0xc9);
  1299. mpack_store_u32(p + 1, count);
  1300. mpack_store_i8(p + 5, exttype);
  1301. }
  1302. MPACK_STATIC_INLINE void mpack_encode_timestamp_4(char* p, uint32_t seconds) {
  1303. mpack_encode_fixext4(p, MPACK_EXTTYPE_TIMESTAMP);
  1304. mpack_store_u32(p + MPACK_TAG_SIZE_FIXEXT4, seconds);
  1305. }
  1306. MPACK_STATIC_INLINE void mpack_encode_timestamp_8(char* p, int64_t seconds, uint32_t nanoseconds) {
  1307. mpack_assert(nanoseconds <= MPACK_TIMESTAMP_NANOSECONDS_MAX);
  1308. mpack_encode_fixext8(p, MPACK_EXTTYPE_TIMESTAMP);
  1309. uint64_t encoded = ((uint64_t)nanoseconds << 34) | (uint64_t)seconds;
  1310. mpack_store_u64(p + MPACK_TAG_SIZE_FIXEXT8, encoded);
  1311. }
  1312. MPACK_STATIC_INLINE void mpack_encode_timestamp_12(char* p, int64_t seconds, uint32_t nanoseconds) {
  1313. mpack_assert(nanoseconds <= MPACK_TIMESTAMP_NANOSECONDS_MAX);
  1314. mpack_encode_ext8(p, MPACK_EXTTYPE_TIMESTAMP, 12);
  1315. mpack_store_u32(p + MPACK_TAG_SIZE_EXT8, nanoseconds);
  1316. mpack_store_i64(p + MPACK_TAG_SIZE_EXT8 + 4, seconds);
  1317. }
  1318. #endif
  1319. /*
  1320. * Write functions
  1321. */
  1322. // This is a macro wrapper to the encode functions to encode
  1323. // directly into the buffer. If mpack_writer_ensure() fails
  1324. // it will flag an error so we don't have to do anything.
  1325. #define MPACK_WRITE_ENCODED(encode_fn, size, ...) do { \
  1326. if (MPACK_LIKELY(mpack_writer_buffer_left(writer) >= size) || mpack_writer_ensure(writer, size)) { \
  1327. MPACK_EXPAND(encode_fn(writer->current, __VA_ARGS__)); \
  1328. writer->current += size; \
  1329. } \
  1330. } while (0)
  1331. void mpack_write_u8(mpack_writer_t* writer, uint8_t value) {
  1332. #if MPACK_OPTIMIZE_FOR_SIZE
  1333. mpack_write_u64(writer, value);
  1334. #else
  1335. mpack_writer_track_element(writer);
  1336. if (value <= 127) {
  1337. MPACK_WRITE_ENCODED(mpack_encode_fixuint, MPACK_TAG_SIZE_FIXUINT, value);
  1338. } else {
  1339. MPACK_WRITE_ENCODED(mpack_encode_u8, MPACK_TAG_SIZE_U8, value);
  1340. }
  1341. #endif
  1342. }
  1343. void mpack_write_u16(mpack_writer_t* writer, uint16_t value) {
  1344. #if MPACK_OPTIMIZE_FOR_SIZE
  1345. mpack_write_u64(writer, value);
  1346. #else
  1347. mpack_writer_track_element(writer);
  1348. if (value <= 127) {
  1349. MPACK_WRITE_ENCODED(mpack_encode_fixuint, MPACK_TAG_SIZE_FIXUINT, (uint8_t)value);
  1350. } else if (value <= UINT8_MAX) {
  1351. MPACK_WRITE_ENCODED(mpack_encode_u8, MPACK_TAG_SIZE_U8, (uint8_t)value);
  1352. } else {
  1353. MPACK_WRITE_ENCODED(mpack_encode_u16, MPACK_TAG_SIZE_U16, value);
  1354. }
  1355. #endif
  1356. }
  1357. void mpack_write_u32(mpack_writer_t* writer, uint32_t value) {
  1358. #if MPACK_OPTIMIZE_FOR_SIZE
  1359. mpack_write_u64(writer, value);
  1360. #else
  1361. mpack_writer_track_element(writer);
  1362. if (value <= 127) {
  1363. MPACK_WRITE_ENCODED(mpack_encode_fixuint, MPACK_TAG_SIZE_FIXUINT, (uint8_t)value);
  1364. } else if (value <= UINT8_MAX) {
  1365. MPACK_WRITE_ENCODED(mpack_encode_u8, MPACK_TAG_SIZE_U8, (uint8_t)value);
  1366. } else if (value <= UINT16_MAX) {
  1367. MPACK_WRITE_ENCODED(mpack_encode_u16, MPACK_TAG_SIZE_U16, (uint16_t)value);
  1368. } else {
  1369. MPACK_WRITE_ENCODED(mpack_encode_u32, MPACK_TAG_SIZE_U32, value);
  1370. }
  1371. #endif
  1372. }
  1373. void mpack_write_u64(mpack_writer_t* writer, uint64_t value) {
  1374. mpack_writer_track_element(writer);
  1375. if (value <= 127) {
  1376. MPACK_WRITE_ENCODED(mpack_encode_fixuint, MPACK_TAG_SIZE_FIXUINT, (uint8_t)value);
  1377. } else if (value <= UINT8_MAX) {
  1378. MPACK_WRITE_ENCODED(mpack_encode_u8, MPACK_TAG_SIZE_U8, (uint8_t)value);
  1379. } else if (value <= UINT16_MAX) {
  1380. MPACK_WRITE_ENCODED(mpack_encode_u16, MPACK_TAG_SIZE_U16, (uint16_t)value);
  1381. } else if (value <= UINT32_MAX) {
  1382. MPACK_WRITE_ENCODED(mpack_encode_u32, MPACK_TAG_SIZE_U32, (uint32_t)value);
  1383. } else {
  1384. MPACK_WRITE_ENCODED(mpack_encode_u64, MPACK_TAG_SIZE_U64, value);
  1385. }
  1386. }
  1387. void mpack_write_i8(mpack_writer_t* writer, int8_t value) {
  1388. #if MPACK_OPTIMIZE_FOR_SIZE
  1389. mpack_write_i64(writer, value);
  1390. #else
  1391. mpack_writer_track_element(writer);
  1392. if (value >= -32) {
  1393. // we encode positive and negative fixints together
  1394. MPACK_WRITE_ENCODED(mpack_encode_fixint, MPACK_TAG_SIZE_FIXINT, (int8_t)value);
  1395. } else {
  1396. MPACK_WRITE_ENCODED(mpack_encode_i8, MPACK_TAG_SIZE_I8, (int8_t)value);
  1397. }
  1398. #endif
  1399. }
  1400. void mpack_write_i16(mpack_writer_t* writer, int16_t value) {
  1401. #if MPACK_OPTIMIZE_FOR_SIZE
  1402. mpack_write_i64(writer, value);
  1403. #else
  1404. mpack_writer_track_element(writer);
  1405. if (value >= -32) {
  1406. if (value <= 127) {
  1407. // we encode positive and negative fixints together
  1408. MPACK_WRITE_ENCODED(mpack_encode_fixint, MPACK_TAG_SIZE_FIXINT, (int8_t)value);
  1409. } else if (value <= UINT8_MAX) {
  1410. MPACK_WRITE_ENCODED(mpack_encode_u8, MPACK_TAG_SIZE_U8, (uint8_t)value);
  1411. } else {
  1412. MPACK_WRITE_ENCODED(mpack_encode_u16, MPACK_TAG_SIZE_U16, (uint16_t)value);
  1413. }
  1414. } else if (value >= INT8_MIN) {
  1415. MPACK_WRITE_ENCODED(mpack_encode_i8, MPACK_TAG_SIZE_I8, (int8_t)value);
  1416. } else {
  1417. MPACK_WRITE_ENCODED(mpack_encode_i16, MPACK_TAG_SIZE_I16, (int16_t)value);
  1418. }
  1419. #endif
  1420. }
  1421. void mpack_write_i32(mpack_writer_t* writer, int32_t value) {
  1422. #if MPACK_OPTIMIZE_FOR_SIZE
  1423. mpack_write_i64(writer, value);
  1424. #else
  1425. mpack_writer_track_element(writer);
  1426. if (value >= -32) {
  1427. if (value <= 127) {
  1428. // we encode positive and negative fixints together
  1429. MPACK_WRITE_ENCODED(mpack_encode_fixint, MPACK_TAG_SIZE_FIXINT, (int8_t)value);
  1430. } else if (value <= UINT8_MAX) {
  1431. MPACK_WRITE_ENCODED(mpack_encode_u8, MPACK_TAG_SIZE_U8, (uint8_t)value);
  1432. } else if (value <= UINT16_MAX) {
  1433. MPACK_WRITE_ENCODED(mpack_encode_u16, MPACK_TAG_SIZE_U16, (uint16_t)value);
  1434. } else {
  1435. MPACK_WRITE_ENCODED(mpack_encode_u32, MPACK_TAG_SIZE_U32, (uint32_t)value);
  1436. }
  1437. } else if (value >= INT8_MIN) {
  1438. MPACK_WRITE_ENCODED(mpack_encode_i8, MPACK_TAG_SIZE_I8, (int8_t)value);
  1439. } else if (value >= INT16_MIN) {
  1440. MPACK_WRITE_ENCODED(mpack_encode_i16, MPACK_TAG_SIZE_I16, (int16_t)value);
  1441. } else {
  1442. MPACK_WRITE_ENCODED(mpack_encode_i32, MPACK_TAG_SIZE_I32, value);
  1443. }
  1444. #endif
  1445. }
  1446. void mpack_write_i64(mpack_writer_t* writer, int64_t value) {
  1447. #if MPACK_OPTIMIZE_FOR_SIZE
  1448. if (value > 127) {
  1449. // for non-fix positive ints we call the u64 writer to save space
  1450. mpack_write_u64(writer, (uint64_t)value);
  1451. return;
  1452. }
  1453. #endif
  1454. mpack_writer_track_element(writer);
  1455. if (value >= -32) {
  1456. #if MPACK_OPTIMIZE_FOR_SIZE
  1457. MPACK_WRITE_ENCODED(mpack_encode_fixint, MPACK_TAG_SIZE_FIXINT, (int8_t)value);
  1458. #else
  1459. if (value <= 127) {
  1460. MPACK_WRITE_ENCODED(mpack_encode_fixint, MPACK_TAG_SIZE_FIXINT, (int8_t)value);
  1461. } else if (value <= UINT8_MAX) {
  1462. MPACK_WRITE_ENCODED(mpack_encode_u8, MPACK_TAG_SIZE_U8, (uint8_t)value);
  1463. } else if (value <= UINT16_MAX) {
  1464. MPACK_WRITE_ENCODED(mpack_encode_u16, MPACK_TAG_SIZE_U16, (uint16_t)value);
  1465. } else if (value <= UINT32_MAX) {
  1466. MPACK_WRITE_ENCODED(mpack_encode_u32, MPACK_TAG_SIZE_U32, (uint32_t)value);
  1467. } else {
  1468. MPACK_WRITE_ENCODED(mpack_encode_u64, MPACK_TAG_SIZE_U64, (uint64_t)value);
  1469. }
  1470. #endif
  1471. } else if (value >= INT8_MIN) {
  1472. MPACK_WRITE_ENCODED(mpack_encode_i8, MPACK_TAG_SIZE_I8, (int8_t)value);
  1473. } else if (value >= INT16_MIN) {
  1474. MPACK_WRITE_ENCODED(mpack_encode_i16, MPACK_TAG_SIZE_I16, (int16_t)value);
  1475. } else if (value >= INT32_MIN) {
  1476. MPACK_WRITE_ENCODED(mpack_encode_i32, MPACK_TAG_SIZE_I32, (int32_t)value);
  1477. } else {
  1478. MPACK_WRITE_ENCODED(mpack_encode_i64, MPACK_TAG_SIZE_I64, value);
  1479. }
  1480. }
  1481. void mpack_write_float(mpack_writer_t* writer, float value) {
  1482. mpack_writer_track_element(writer);
  1483. MPACK_WRITE_ENCODED(mpack_encode_float, MPACK_TAG_SIZE_FLOAT, value);
  1484. }
  1485. void mpack_write_double(mpack_writer_t* writer, double value) {
  1486. mpack_writer_track_element(writer);
  1487. MPACK_WRITE_ENCODED(mpack_encode_double, MPACK_TAG_SIZE_DOUBLE, value);
  1488. }
  1489. #if MPACK_EXTENSIONS
  1490. void mpack_write_timestamp(mpack_writer_t* writer, int64_t seconds, uint32_t nanoseconds) {
  1491. #if MPACK_COMPATIBILITY
  1492. if (writer->version <= mpack_version_v4) {
  1493. mpack_break("Timestamps require spec version v5 or later. This writer is in v%i mode.", (int)writer->version);
  1494. mpack_writer_flag_error(writer, mpack_error_bug);
  1495. return;
  1496. }
  1497. #endif
  1498. if (nanoseconds > MPACK_TIMESTAMP_NANOSECONDS_MAX) {
  1499. mpack_break("timestamp nanoseconds out of bounds: %u", nanoseconds);
  1500. mpack_writer_flag_error(writer, mpack_error_bug);
  1501. return;
  1502. }
  1503. mpack_writer_track_element(writer);
  1504. if (seconds < 0 || seconds >= (INT64_C(1) << 34)) {
  1505. MPACK_WRITE_ENCODED(mpack_encode_timestamp_12, MPACK_EXT_SIZE_TIMESTAMP12, seconds, nanoseconds);
  1506. } else if (seconds > UINT32_MAX || nanoseconds > 0) {
  1507. MPACK_WRITE_ENCODED(mpack_encode_timestamp_8, MPACK_EXT_SIZE_TIMESTAMP8, seconds, nanoseconds);
  1508. } else {
  1509. MPACK_WRITE_ENCODED(mpack_encode_timestamp_4, MPACK_EXT_SIZE_TIMESTAMP4, (uint32_t)seconds);
  1510. }
  1511. }
  1512. #endif
  1513. void mpack_start_array(mpack_writer_t* writer, uint32_t count) {
  1514. mpack_writer_track_element(writer);
  1515. if (count <= 15) {
  1516. MPACK_WRITE_ENCODED(mpack_encode_fixarray, MPACK_TAG_SIZE_FIXARRAY, (uint8_t)count);
  1517. } else if (count <= UINT16_MAX) {
  1518. MPACK_WRITE_ENCODED(mpack_encode_array16, MPACK_TAG_SIZE_ARRAY16, (uint16_t)count);
  1519. } else {
  1520. MPACK_WRITE_ENCODED(mpack_encode_array32, MPACK_TAG_SIZE_ARRAY32, (uint32_t)count);
  1521. }
  1522. mpack_writer_track_push(writer, mpack_type_array, count);
  1523. }
  1524. void mpack_start_map(mpack_writer_t* writer, uint32_t count) {
  1525. mpack_writer_track_element(writer);
  1526. if (count <= 15) {
  1527. MPACK_WRITE_ENCODED(mpack_encode_fixmap, MPACK_TAG_SIZE_FIXMAP, (uint8_t)count);
  1528. } else if (count <= UINT16_MAX) {
  1529. MPACK_WRITE_ENCODED(mpack_encode_map16, MPACK_TAG_SIZE_MAP16, (uint16_t)count);
  1530. } else {
  1531. MPACK_WRITE_ENCODED(mpack_encode_map32, MPACK_TAG_SIZE_MAP32, (uint32_t)count);
  1532. }
  1533. mpack_writer_track_push(writer, mpack_type_map, count);
  1534. }
  1535. static void mpack_start_str_notrack(mpack_writer_t* writer, uint32_t count) {
  1536. if (count <= 31) {
  1537. MPACK_WRITE_ENCODED(mpack_encode_fixstr, MPACK_TAG_SIZE_FIXSTR, (uint8_t)count);
  1538. // str8 is only supported in v5 or later.
  1539. } else if (count <= UINT8_MAX
  1540. #if MPACK_COMPATIBILITY
  1541. && writer->version >= mpack_version_v5
  1542. #endif
  1543. ) {
  1544. MPACK_WRITE_ENCODED(mpack_encode_str8, MPACK_TAG_SIZE_STR8, (uint8_t)count);
  1545. } else if (count <= UINT16_MAX) {
  1546. MPACK_WRITE_ENCODED(mpack_encode_str16, MPACK_TAG_SIZE_STR16, (uint16_t)count);
  1547. } else {
  1548. MPACK_WRITE_ENCODED(mpack_encode_str32, MPACK_TAG_SIZE_STR32, (uint32_t)count);
  1549. }
  1550. }
  1551. static void mpack_start_bin_notrack(mpack_writer_t* writer, uint32_t count) {
  1552. #if MPACK_COMPATIBILITY
  1553. // In the v4 spec, there was only the raw type for any kind of
  1554. // variable-length data. In v4 mode, we support the bin functions,
  1555. // but we produce an old-style raw.
  1556. if (writer->version <= mpack_version_v4) {
  1557. mpack_start_str_notrack(writer, count);
  1558. return;
  1559. }
  1560. #endif
  1561. if (count <= UINT8_MAX) {
  1562. MPACK_WRITE_ENCODED(mpack_encode_bin8, MPACK_TAG_SIZE_BIN8, (uint8_t)count);
  1563. } else if (count <= UINT16_MAX) {
  1564. MPACK_WRITE_ENCODED(mpack_encode_bin16, MPACK_TAG_SIZE_BIN16, (uint16_t)count);
  1565. } else {
  1566. MPACK_WRITE_ENCODED(mpack_encode_bin32, MPACK_TAG_SIZE_BIN32, (uint32_t)count);
  1567. }
  1568. }
  1569. void mpack_start_str(mpack_writer_t* writer, uint32_t count) {
  1570. mpack_writer_track_element(writer);
  1571. mpack_start_str_notrack(writer, count);
  1572. mpack_writer_track_push(writer, mpack_type_str, count);
  1573. }
  1574. void mpack_start_bin(mpack_writer_t* writer, uint32_t count) {
  1575. mpack_writer_track_element(writer);
  1576. mpack_start_bin_notrack(writer, count);
  1577. mpack_writer_track_push(writer, mpack_type_bin, count);
  1578. }
  1579. #if MPACK_EXTENSIONS
  1580. void mpack_start_ext(mpack_writer_t* writer, int8_t exttype, uint32_t count) {
  1581. #if MPACK_COMPATIBILITY
  1582. if (writer->version <= mpack_version_v4) {
  1583. mpack_break("Ext types require spec version v5 or later. This writer is in v%i mode.", (int)writer->version);
  1584. mpack_writer_flag_error(writer, mpack_error_bug);
  1585. return;
  1586. }
  1587. #endif
  1588. mpack_writer_track_element(writer);
  1589. if (count == 1) {
  1590. MPACK_WRITE_ENCODED(mpack_encode_fixext1, MPACK_TAG_SIZE_FIXEXT1, exttype);
  1591. } else if (count == 2) {
  1592. MPACK_WRITE_ENCODED(mpack_encode_fixext2, MPACK_TAG_SIZE_FIXEXT2, exttype);
  1593. } else if (count == 4) {
  1594. MPACK_WRITE_ENCODED(mpack_encode_fixext4, MPACK_TAG_SIZE_FIXEXT4, exttype);
  1595. } else if (count == 8) {
  1596. MPACK_WRITE_ENCODED(mpack_encode_fixext8, MPACK_TAG_SIZE_FIXEXT8, exttype);
  1597. } else if (count == 16) {
  1598. MPACK_WRITE_ENCODED(mpack_encode_fixext16, MPACK_TAG_SIZE_FIXEXT16, exttype);
  1599. } else if (count <= UINT8_MAX) {
  1600. MPACK_WRITE_ENCODED(mpack_encode_ext8, MPACK_TAG_SIZE_EXT8, exttype, (uint8_t)count);
  1601. } else if (count <= UINT16_MAX) {
  1602. MPACK_WRITE_ENCODED(mpack_encode_ext16, MPACK_TAG_SIZE_EXT16, exttype, (uint16_t)count);
  1603. } else {
  1604. MPACK_WRITE_ENCODED(mpack_encode_ext32, MPACK_TAG_SIZE_EXT32, exttype, (uint32_t)count);
  1605. }
  1606. mpack_writer_track_push(writer, mpack_type_ext, count);
  1607. }
  1608. #endif
  1609. /*
  1610. * Compound helpers and other functions
  1611. */
  1612. void mpack_write_str(mpack_writer_t* writer, const char* data, uint32_t count) {
  1613. mpack_assert(data != NULL, "data for string of length %i is NULL", (int)count);
  1614. #if MPACK_OPTIMIZE_FOR_SIZE
  1615. mpack_writer_track_element(writer);
  1616. mpack_start_str_notrack(writer, count);
  1617. mpack_write_native(writer, data, count);
  1618. #else
  1619. mpack_writer_track_element(writer);
  1620. if (count <= 31) {
  1621. // The minimum buffer size when using a flush function is guaranteed to
  1622. // fit the largest possible fixstr.
  1623. size_t size = count + MPACK_TAG_SIZE_FIXSTR;
  1624. if (MPACK_LIKELY(mpack_writer_buffer_left(writer) >= size) || mpack_writer_ensure(writer, size)) {
  1625. char* MPACK_RESTRICT p = writer->current;
  1626. mpack_encode_fixstr(p, (uint8_t)count);
  1627. mpack_memcpy(p + MPACK_TAG_SIZE_FIXSTR, data, count);
  1628. writer->current += count + MPACK_TAG_SIZE_FIXSTR;
  1629. }
  1630. return;
  1631. }
  1632. if (count <= UINT8_MAX
  1633. #if MPACK_COMPATIBILITY
  1634. && writer->version >= mpack_version_v5
  1635. #endif
  1636. ) {
  1637. if (count + MPACK_TAG_SIZE_STR8 <= mpack_writer_buffer_left(writer)) {
  1638. char* MPACK_RESTRICT p = writer->current;
  1639. mpack_encode_str8(p, (uint8_t)count);
  1640. mpack_memcpy(p + MPACK_TAG_SIZE_STR8, data, count);
  1641. writer->current += count + MPACK_TAG_SIZE_STR8;
  1642. } else {
  1643. MPACK_WRITE_ENCODED(mpack_encode_str8, MPACK_TAG_SIZE_STR8, (uint8_t)count);
  1644. mpack_write_native(writer, data, count);
  1645. }
  1646. return;
  1647. }
  1648. // str16 and str32 are likely to be a significant fraction of the buffer
  1649. // size, so we don't bother with a combined space check in order to
  1650. // minimize code size.
  1651. if (count <= UINT16_MAX) {
  1652. MPACK_WRITE_ENCODED(mpack_encode_str16, MPACK_TAG_SIZE_STR16, (uint16_t)count);
  1653. mpack_write_native(writer, data, count);
  1654. } else {
  1655. MPACK_WRITE_ENCODED(mpack_encode_str32, MPACK_TAG_SIZE_STR32, (uint32_t)count);
  1656. mpack_write_native(writer, data, count);
  1657. }
  1658. #endif
  1659. }
  1660. void mpack_write_bin(mpack_writer_t* writer, const char* data, uint32_t count) {
  1661. mpack_assert(data != NULL, "data pointer for bin of %i bytes is NULL", (int)count);
  1662. mpack_start_bin(writer, count);
  1663. mpack_write_bytes(writer, data, count);
  1664. mpack_finish_bin(writer);
  1665. }
  1666. #if MPACK_EXTENSIONS
  1667. void mpack_write_ext(mpack_writer_t* writer, int8_t exttype, const char* data, uint32_t count) {
  1668. mpack_assert(data != NULL, "data pointer for ext of type %i and %i bytes is NULL", exttype, (int)count);
  1669. mpack_start_ext(writer, exttype, count);
  1670. mpack_write_bytes(writer, data, count);
  1671. mpack_finish_ext(writer);
  1672. }
  1673. #endif
  1674. void mpack_write_bytes(mpack_writer_t* writer, const char* data, size_t count) {
  1675. mpack_assert(data != NULL, "data pointer for %i bytes is NULL", (int)count);
  1676. mpack_writer_track_bytes(writer, count);
  1677. mpack_write_native(writer, data, count);
  1678. }
  1679. void mpack_write_cstr(mpack_writer_t* writer, const char* cstr) {
  1680. mpack_assert(cstr != NULL, "cstr pointer is NULL");
  1681. size_t length = mpack_strlen(cstr);
  1682. if (length > UINT32_MAX)
  1683. mpack_writer_flag_error(writer, mpack_error_invalid);
  1684. mpack_write_str(writer, cstr, (uint32_t)length);
  1685. }
  1686. void mpack_write_cstr_or_nil(mpack_writer_t* writer, const char* cstr) {
  1687. if (cstr)
  1688. mpack_write_cstr(writer, cstr);
  1689. else
  1690. mpack_write_nil(writer);
  1691. }
  1692. void mpack_write_utf8(mpack_writer_t* writer, const char* str, uint32_t length) {
  1693. mpack_assert(str != NULL, "data for string of length %i is NULL", (int)length);
  1694. if (!mpack_utf8_check(str, length)) {
  1695. mpack_writer_flag_error(writer, mpack_error_invalid);
  1696. return;
  1697. }
  1698. mpack_write_str(writer, str, length);
  1699. }
  1700. void mpack_write_utf8_cstr(mpack_writer_t* writer, const char* cstr) {
  1701. mpack_assert(cstr != NULL, "cstr pointer is NULL");
  1702. size_t length = mpack_strlen(cstr);
  1703. if (length > UINT32_MAX) {
  1704. mpack_writer_flag_error(writer, mpack_error_invalid);
  1705. return;
  1706. }
  1707. mpack_write_utf8(writer, cstr, (uint32_t)length);
  1708. }
  1709. void mpack_write_utf8_cstr_or_nil(mpack_writer_t* writer, const char* cstr) {
  1710. if (cstr)
  1711. mpack_write_utf8_cstr(writer, cstr);
  1712. else
  1713. mpack_write_nil(writer);
  1714. }
  1715. #endif
  1716. /* mpack/mpack-reader.c.c */
  1717. #define MPACK_INTERNAL 1
  1718. /* #include "mpack-reader.h" */
  1719. #if MPACK_READER
  1720. static void mpack_reader_skip_using_fill(mpack_reader_t* reader, size_t count);
  1721. void mpack_reader_init(mpack_reader_t* reader, char* buffer, size_t size, size_t count) {
  1722. mpack_assert(buffer != NULL, "buffer is NULL");
  1723. mpack_memset(reader, 0, sizeof(*reader));
  1724. reader->buffer = buffer;
  1725. reader->size = size;
  1726. reader->data = buffer;
  1727. reader->end = buffer + count;
  1728. #if MPACK_READ_TRACKING
  1729. mpack_reader_flag_if_error(reader, mpack_track_init(&reader->track));
  1730. #endif
  1731. mpack_log("===========================\n");
  1732. mpack_log("initializing reader with buffer size %i\n", (int)size);
  1733. }
  1734. void mpack_reader_init_error(mpack_reader_t* reader, mpack_error_t error) {
  1735. mpack_memset(reader, 0, sizeof(*reader));
  1736. reader->error = error;
  1737. mpack_log("===========================\n");
  1738. mpack_log("initializing reader error state %i\n", (int)error);
  1739. }
  1740. void mpack_reader_init_data(mpack_reader_t* reader, const char* data, size_t count) {
  1741. mpack_assert(data != NULL, "data is NULL");
  1742. mpack_memset(reader, 0, sizeof(*reader));
  1743. reader->data = data;
  1744. reader->end = data + count;
  1745. #if MPACK_READ_TRACKING
  1746. mpack_reader_flag_if_error(reader, mpack_track_init(&reader->track));
  1747. #endif
  1748. mpack_log("===========================\n");
  1749. mpack_log("initializing reader with data size %i\n", (int)count);
  1750. }
  1751. void mpack_reader_set_fill(mpack_reader_t* reader, mpack_reader_fill_t fill) {
  1752. MPACK_STATIC_ASSERT(MPACK_READER_MINIMUM_BUFFER_SIZE >= MPACK_MAXIMUM_TAG_SIZE,
  1753. "minimum buffer size must fit any tag!");
  1754. if (reader->size == 0) {
  1755. mpack_break("cannot use fill function without a writeable buffer!");
  1756. mpack_reader_flag_error(reader, mpack_error_bug);
  1757. return;
  1758. }
  1759. if (reader->size < MPACK_READER_MINIMUM_BUFFER_SIZE) {
  1760. mpack_break("buffer size is %i, but minimum buffer size for fill is %i",
  1761. (int)reader->size, MPACK_READER_MINIMUM_BUFFER_SIZE);
  1762. mpack_reader_flag_error(reader, mpack_error_bug);
  1763. return;
  1764. }
  1765. reader->fill = fill;
  1766. }
  1767. void mpack_reader_set_skip(mpack_reader_t* reader, mpack_reader_skip_t skip) {
  1768. mpack_assert(reader->size != 0, "cannot use skip function without a writeable buffer!");
  1769. reader->skip = skip;
  1770. }
  1771. #if MPACK_STDIO
  1772. static size_t mpack_file_reader_fill(mpack_reader_t* reader, char* buffer, size_t count) {
  1773. if (feof((FILE *)reader->context)) {
  1774. mpack_reader_flag_error(reader, mpack_error_eof);
  1775. return 0;
  1776. }
  1777. return fread((void*)buffer, 1, count, (FILE*)reader->context);
  1778. }
  1779. static void mpack_file_reader_skip(mpack_reader_t* reader, size_t count) {
  1780. if (mpack_reader_error(reader) != mpack_ok)
  1781. return;
  1782. FILE* file = (FILE*)reader->context;
  1783. // We call ftell() to test whether the stream is seekable
  1784. // without causing a file error.
  1785. if (ftell(file) >= 0) {
  1786. mpack_log("seeking forward %i bytes\n", (int)count);
  1787. if (fseek(file, (long int)count, SEEK_CUR) == 0)
  1788. return;
  1789. mpack_log("fseek() didn't return zero!\n");
  1790. if (ferror(file)) {
  1791. mpack_reader_flag_error(reader, mpack_error_io);
  1792. return;
  1793. }
  1794. }
  1795. // If the stream is not seekable, fall back to the fill function.
  1796. mpack_reader_skip_using_fill(reader, count);
  1797. }
  1798. static void mpack_file_reader_teardown(mpack_reader_t* reader) {
  1799. MPACK_FREE(reader->buffer);
  1800. reader->buffer = NULL;
  1801. reader->context = NULL;
  1802. reader->size = 0;
  1803. reader->fill = NULL;
  1804. reader->skip = NULL;
  1805. reader->teardown = NULL;
  1806. }
  1807. static void mpack_file_reader_teardown_close(mpack_reader_t* reader) {
  1808. FILE* file = (FILE*)reader->context;
  1809. if (file) {
  1810. int ret = fclose(file);
  1811. if (ret != 0)
  1812. mpack_reader_flag_error(reader, mpack_error_io);
  1813. }
  1814. mpack_file_reader_teardown(reader);
  1815. }
  1816. void mpack_reader_init_stdfile(mpack_reader_t* reader, FILE* file, bool close_when_done) {
  1817. mpack_assert(file != NULL, "file is NULL");
  1818. size_t capacity = MPACK_BUFFER_SIZE;
  1819. char* buffer = (char*)MPACK_MALLOC(capacity);
  1820. if (buffer == NULL) {
  1821. mpack_reader_init_error(reader, mpack_error_memory);
  1822. if (close_when_done) {
  1823. fclose(file);
  1824. }
  1825. return;
  1826. }
  1827. mpack_reader_init(reader, buffer, capacity, 0);
  1828. mpack_reader_set_context(reader, file);
  1829. mpack_reader_set_fill(reader, mpack_file_reader_fill);
  1830. mpack_reader_set_skip(reader, mpack_file_reader_skip);
  1831. mpack_reader_set_teardown(reader, close_when_done ?
  1832. mpack_file_reader_teardown_close :
  1833. mpack_file_reader_teardown);
  1834. }
  1835. void mpack_reader_init_filename(mpack_reader_t* reader, const char* filename) {
  1836. mpack_assert(filename != NULL, "filename is NULL");
  1837. FILE* file = fopen(filename, "rb");
  1838. if (file == NULL) {
  1839. mpack_reader_init_error(reader, mpack_error_io);
  1840. return;
  1841. }
  1842. mpack_reader_init_stdfile(reader, file, true);
  1843. }
  1844. #endif
  1845. mpack_error_t mpack_reader_destroy(mpack_reader_t* reader) {
  1846. // clean up tracking, asserting if we're not already in an error state
  1847. #if MPACK_READ_TRACKING
  1848. mpack_reader_flag_if_error(reader, mpack_track_destroy(&reader->track, mpack_reader_error(reader) != mpack_ok));
  1849. #endif
  1850. if (reader->teardown)
  1851. reader->teardown(reader);
  1852. reader->teardown = NULL;
  1853. return reader->error;
  1854. }
  1855. size_t mpack_reader_remaining(mpack_reader_t* reader, const char** data) {
  1856. if (mpack_reader_error(reader) != mpack_ok)
  1857. return 0;
  1858. #if MPACK_READ_TRACKING
  1859. if (mpack_reader_flag_if_error(reader, mpack_track_check_empty(&reader->track)) != mpack_ok)
  1860. return 0;
  1861. #endif
  1862. if (data)
  1863. *data = reader->data;
  1864. return (size_t)(reader->end - reader->data);
  1865. }
  1866. void mpack_reader_flag_error(mpack_reader_t* reader, mpack_error_t error) {
  1867. mpack_log("reader %p setting error %i: %s\n", reader, (int)error, mpack_error_to_string(error));
  1868. if (reader->error == mpack_ok) {
  1869. reader->error = error;
  1870. reader->end = reader->data;
  1871. if (reader->error_fn)
  1872. reader->error_fn(reader, error);
  1873. }
  1874. }
  1875. // Loops on the fill function, reading between the minimum and
  1876. // maximum number of bytes and flagging an error if it fails.
  1877. MPACK_NOINLINE static size_t mpack_fill_range(mpack_reader_t* reader, char* p, size_t min_bytes, size_t max_bytes) {
  1878. mpack_assert(reader->fill != NULL, "mpack_fill_range() called with no fill function?");
  1879. mpack_assert(min_bytes > 0, "cannot fill zero bytes!");
  1880. mpack_assert(max_bytes >= min_bytes, "min_bytes %i cannot be larger than max_bytes %i!",
  1881. (int)min_bytes, (int)max_bytes);
  1882. size_t count = 0;
  1883. while (count < min_bytes) {
  1884. size_t read = reader->fill(reader, p + count, max_bytes - count);
  1885. // Reader fill functions can flag an error or return 0 on failure. We
  1886. // also guard against functions that -1 just in case.
  1887. if (mpack_reader_error(reader) != mpack_ok)
  1888. return 0;
  1889. if (read == 0 || read == ((size_t)(-1))) {
  1890. mpack_reader_flag_error(reader, mpack_error_io);
  1891. return 0;
  1892. }
  1893. count += read;
  1894. }
  1895. return count;
  1896. }
  1897. MPACK_NOINLINE bool mpack_reader_ensure_straddle(mpack_reader_t* reader, size_t count) {
  1898. mpack_assert(count != 0, "cannot ensure zero bytes!");
  1899. mpack_assert(reader->error == mpack_ok, "reader cannot be in an error state!");
  1900. mpack_assert(count > (size_t)(reader->end - reader->data),
  1901. "straddling ensure requested for %i bytes, but there are %i bytes "
  1902. "left in buffer. call mpack_reader_ensure() instead",
  1903. (int)count, (int)(reader->end - reader->data));
  1904. // we'll need a fill function to get more data. if there's no
  1905. // fill function, the buffer should contain an entire MessagePack
  1906. // object, so we raise mpack_error_invalid instead of mpack_error_io
  1907. // on truncated data.
  1908. if (reader->fill == NULL) {
  1909. mpack_reader_flag_error(reader, mpack_error_invalid);
  1910. return false;
  1911. }
  1912. // we need enough space in the buffer. if the buffer is not
  1913. // big enough, we return mpack_error_too_big (since this is
  1914. // for an in-place read larger than the buffer size.)
  1915. if (count > reader->size) {
  1916. mpack_reader_flag_error(reader, mpack_error_too_big);
  1917. return false;
  1918. }
  1919. // move the existing data to the start of the buffer
  1920. size_t left = (size_t)(reader->end - reader->data);
  1921. mpack_memmove(reader->buffer, reader->data, left);
  1922. reader->end -= reader->data - reader->buffer;
  1923. reader->data = reader->buffer;
  1924. // read at least the necessary number of bytes, accepting up to the
  1925. // buffer size
  1926. size_t read = mpack_fill_range(reader, reader->buffer + left,
  1927. count - left, reader->size - left);
  1928. if (mpack_reader_error(reader) != mpack_ok)
  1929. return false;
  1930. reader->end += read;
  1931. return true;
  1932. }
  1933. // Reads count bytes into p. Used when there are not enough bytes
  1934. // left in the buffer to satisfy a read.
  1935. MPACK_NOINLINE void mpack_read_native_straddle(mpack_reader_t* reader, char* p, size_t count) {
  1936. mpack_assert(count == 0 || p != NULL, "data pointer for %i bytes is NULL", (int)count);
  1937. if (mpack_reader_error(reader) != mpack_ok) {
  1938. mpack_memset(p, 0, count);
  1939. return;
  1940. }
  1941. size_t left = (size_t)(reader->end - reader->data);
  1942. mpack_log("big read for %i bytes into %p, %i left in buffer, buffer size %i\n",
  1943. (int)count, p, (int)left, (int)reader->size);
  1944. if (count <= left) {
  1945. mpack_assert(0,
  1946. "big read requested for %i bytes, but there are %i bytes "
  1947. "left in buffer. call mpack_read_native() instead",
  1948. (int)count, (int)left);
  1949. mpack_reader_flag_error(reader, mpack_error_bug);
  1950. mpack_memset(p, 0, count);
  1951. return;
  1952. }
  1953. // we'll need a fill function to get more data. if there's no
  1954. // fill function, the buffer should contain an entire MessagePack
  1955. // object, so we raise mpack_error_invalid instead of mpack_error_io
  1956. // on truncated data.
  1957. if (reader->fill == NULL) {
  1958. mpack_reader_flag_error(reader, mpack_error_invalid);
  1959. mpack_memset(p, 0, count);
  1960. return;
  1961. }
  1962. if (reader->size == 0) {
  1963. // somewhat debatable what error should be returned here. when
  1964. // initializing a reader with an in-memory buffer it's not
  1965. // necessarily a bug if the data is blank; it might just have
  1966. // been truncated to zero. for this reason we return the same
  1967. // error as if the data was truncated.
  1968. mpack_reader_flag_error(reader, mpack_error_io);
  1969. mpack_memset(p, 0, count);
  1970. return;
  1971. }
  1972. // flush what's left of the buffer
  1973. if (left > 0) {
  1974. mpack_log("flushing %i bytes remaining in buffer\n", (int)left);
  1975. mpack_memcpy(p, reader->data, left);
  1976. count -= left;
  1977. p += left;
  1978. reader->data += left;
  1979. }
  1980. // if the remaining data needed is some small fraction of the
  1981. // buffer size, we'll try to fill the buffer as much as possible
  1982. // and copy the needed data out.
  1983. if (count <= reader->size / MPACK_READER_SMALL_FRACTION_DENOMINATOR) {
  1984. size_t read = mpack_fill_range(reader, reader->buffer, count, reader->size);
  1985. if (mpack_reader_error(reader) != mpack_ok)
  1986. return;
  1987. mpack_memcpy(p, reader->buffer, count);
  1988. reader->data = reader->buffer + count;
  1989. reader->end = reader->buffer + read;
  1990. // otherwise we read the remaining data directly into the target.
  1991. } else {
  1992. mpack_log("reading %i additional bytes\n", (int)count);
  1993. mpack_fill_range(reader, p, count, count);
  1994. }
  1995. }
  1996. MPACK_NOINLINE static void mpack_skip_bytes_straddle(mpack_reader_t* reader, size_t count) {
  1997. // we'll need at least a fill function to skip more data. if there's
  1998. // no fill function, the buffer should contain an entire MessagePack
  1999. // object, so we raise mpack_error_invalid instead of mpack_error_io
  2000. // on truncated data. (see mpack_read_native_straddle())
  2001. if (reader->fill == NULL) {
  2002. mpack_log("reader has no fill function!\n");
  2003. mpack_reader_flag_error(reader, mpack_error_invalid);
  2004. return;
  2005. }
  2006. // discard whatever's left in the buffer
  2007. size_t left = (size_t)(reader->end - reader->data);
  2008. mpack_log("discarding %i bytes still in buffer\n", (int)left);
  2009. count -= left;
  2010. reader->data = reader->end;
  2011. // use the skip function if we've got one, and if we're trying
  2012. // to skip a lot of data. if we only need to skip some tiny
  2013. // fraction of the buffer size, it's probably better to just
  2014. // fill the buffer and skip from it instead of trying to seek.
  2015. if (reader->skip && count > reader->size / 16) {
  2016. mpack_log("calling skip function for %i bytes\n", (int)count);
  2017. reader->skip(reader, count);
  2018. return;
  2019. }
  2020. mpack_reader_skip_using_fill(reader, count);
  2021. }
  2022. void mpack_skip_bytes(mpack_reader_t* reader, size_t count) {
  2023. if (mpack_reader_error(reader) != mpack_ok)
  2024. return;
  2025. mpack_log("skip requested for %i bytes\n", (int)count);
  2026. mpack_reader_track_bytes(reader, count);
  2027. // check if we have enough in the buffer already
  2028. size_t left = (size_t)(reader->end - reader->data);
  2029. if (left >= count) {
  2030. mpack_log("skipping %i bytes still in buffer\n", (int)count);
  2031. reader->data += count;
  2032. return;
  2033. }
  2034. mpack_skip_bytes_straddle(reader, count);
  2035. }
  2036. MPACK_NOINLINE static void mpack_reader_skip_using_fill(mpack_reader_t* reader, size_t count) {
  2037. mpack_assert(reader->fill != NULL, "missing fill function!");
  2038. mpack_assert(reader->data == reader->end, "there are bytes left in the buffer!");
  2039. mpack_assert(reader->error == mpack_ok, "should not have called this in an error state (%i)", reader->error);
  2040. mpack_log("skip using fill for %i bytes\n", (int)count);
  2041. // fill and discard multiples of the buffer size
  2042. while (count > reader->size) {
  2043. mpack_log("filling and discarding buffer of %i bytes\n", (int)reader->size);
  2044. if (mpack_fill_range(reader, reader->buffer, reader->size, reader->size) < reader->size) {
  2045. mpack_reader_flag_error(reader, mpack_error_io);
  2046. return;
  2047. }
  2048. count -= reader->size;
  2049. }
  2050. // fill the buffer as much as possible
  2051. reader->data = reader->buffer;
  2052. size_t read = mpack_fill_range(reader, reader->buffer, count, reader->size);
  2053. if (read < count) {
  2054. mpack_reader_flag_error(reader, mpack_error_io);
  2055. return;
  2056. }
  2057. reader->end = reader->data + read;
  2058. mpack_log("filled %i bytes into buffer; discarding %i bytes\n", (int)read, (int)count);
  2059. reader->data += count;
  2060. }
  2061. void mpack_read_bytes(mpack_reader_t* reader, char* p, size_t count) {
  2062. mpack_assert(p != NULL, "destination for read of %i bytes is NULL", (int)count);
  2063. mpack_reader_track_bytes(reader, count);
  2064. mpack_read_native(reader, p, count);
  2065. }
  2066. void mpack_read_utf8(mpack_reader_t* reader, char* p, size_t byte_count) {
  2067. mpack_assert(p != NULL, "destination for read of %i bytes is NULL", (int)byte_count);
  2068. mpack_reader_track_str_bytes_all(reader, byte_count);
  2069. mpack_read_native(reader, p, byte_count);
  2070. if (mpack_reader_error(reader) == mpack_ok && !mpack_utf8_check(p, byte_count))
  2071. mpack_reader_flag_error(reader, mpack_error_type);
  2072. }
  2073. static void mpack_read_cstr_unchecked(mpack_reader_t* reader, char* buf, size_t buffer_size, size_t byte_count) {
  2074. mpack_assert(buf != NULL, "destination for read of %i bytes is NULL", (int)byte_count);
  2075. mpack_assert(buffer_size >= 1, "buffer size is zero; you must have room for at least a null-terminator");
  2076. if (mpack_reader_error(reader)) {
  2077. buf[0] = 0;
  2078. return;
  2079. }
  2080. if (byte_count > buffer_size - 1) {
  2081. mpack_reader_flag_error(reader, mpack_error_too_big);
  2082. buf[0] = 0;
  2083. return;
  2084. }
  2085. mpack_reader_track_str_bytes_all(reader, byte_count);
  2086. mpack_read_native(reader, buf, byte_count);
  2087. buf[byte_count] = 0;
  2088. }
  2089. void mpack_read_cstr(mpack_reader_t* reader, char* buf, size_t buffer_size, size_t byte_count) {
  2090. mpack_read_cstr_unchecked(reader, buf, buffer_size, byte_count);
  2091. // check for null bytes
  2092. if (mpack_reader_error(reader) == mpack_ok && !mpack_str_check_no_null(buf, byte_count)) {
  2093. buf[0] = 0;
  2094. mpack_reader_flag_error(reader, mpack_error_type);
  2095. }
  2096. }
  2097. void mpack_read_utf8_cstr(mpack_reader_t* reader, char* buf, size_t buffer_size, size_t byte_count) {
  2098. mpack_read_cstr_unchecked(reader, buf, buffer_size, byte_count);
  2099. // check encoding
  2100. if (mpack_reader_error(reader) == mpack_ok && !mpack_utf8_check_no_null(buf, byte_count)) {
  2101. buf[0] = 0;
  2102. mpack_reader_flag_error(reader, mpack_error_type);
  2103. }
  2104. }
  2105. #ifdef MPACK_MALLOC
  2106. // Reads native bytes with error callback disabled. This allows MPack reader functions
  2107. // to hold an allocated buffer and read native data into it without leaking it in
  2108. // case of a non-local jump (longjmp, throw) out of an error handler.
  2109. static void mpack_read_native_noerrorfn(mpack_reader_t* reader, char* p, size_t count) {
  2110. mpack_assert(reader->error == mpack_ok, "cannot call if an error is already flagged!");
  2111. mpack_reader_error_t error_fn = reader->error_fn;
  2112. reader->error_fn = NULL;
  2113. mpack_read_native(reader, p, count);
  2114. reader->error_fn = error_fn;
  2115. }
  2116. char* mpack_read_bytes_alloc_impl(mpack_reader_t* reader, size_t count, bool null_terminated) {
  2117. // track the bytes first in case it jumps
  2118. mpack_reader_track_bytes(reader, count);
  2119. if (mpack_reader_error(reader) != mpack_ok)
  2120. return NULL;
  2121. // cannot allocate zero bytes. this is not an error.
  2122. if (count == 0 && null_terminated == false)
  2123. return NULL;
  2124. // allocate data
  2125. char* data = (char*)MPACK_MALLOC(count + (null_terminated ? 1 : 0)); // TODO: can this overflow?
  2126. if (data == NULL) {
  2127. mpack_reader_flag_error(reader, mpack_error_memory);
  2128. return NULL;
  2129. }
  2130. // read with error callback disabled so we don't leak our buffer
  2131. mpack_read_native_noerrorfn(reader, data, count);
  2132. // report flagged errors
  2133. if (mpack_reader_error(reader) != mpack_ok) {
  2134. MPACK_FREE(data);
  2135. if (reader->error_fn)
  2136. reader->error_fn(reader, mpack_reader_error(reader));
  2137. return NULL;
  2138. }
  2139. if (null_terminated)
  2140. data[count] = '\0';
  2141. return data;
  2142. }
  2143. #endif
  2144. // read inplace without tracking (since there are different
  2145. // tracking modes for different inplace readers)
  2146. static const char* mpack_read_bytes_inplace_notrack(mpack_reader_t* reader, size_t count) {
  2147. if (mpack_reader_error(reader) != mpack_ok)
  2148. return NULL;
  2149. // if we have enough bytes already in the buffer, we can return it directly.
  2150. if ((size_t)(reader->end - reader->data) >= count) {
  2151. const char* bytes = reader->data;
  2152. reader->data += count;
  2153. return bytes;
  2154. }
  2155. if (!mpack_reader_ensure(reader, count))
  2156. return NULL;
  2157. const char* bytes = reader->data;
  2158. reader->data += count;
  2159. return bytes;
  2160. }
  2161. const char* mpack_read_bytes_inplace(mpack_reader_t* reader, size_t count) {
  2162. mpack_reader_track_bytes(reader, count);
  2163. return mpack_read_bytes_inplace_notrack(reader, count);
  2164. }
  2165. const char* mpack_read_utf8_inplace(mpack_reader_t* reader, size_t count) {
  2166. mpack_reader_track_str_bytes_all(reader, count);
  2167. const char* str = mpack_read_bytes_inplace_notrack(reader, count);
  2168. if (mpack_reader_error(reader) == mpack_ok && !mpack_utf8_check(str, count)) {
  2169. mpack_reader_flag_error(reader, mpack_error_type);
  2170. return NULL;
  2171. }
  2172. return str;
  2173. }
  2174. static size_t mpack_parse_tag(mpack_reader_t* reader, mpack_tag_t* tag) {
  2175. mpack_assert(reader->error == mpack_ok, "reader cannot be in an error state!");
  2176. if (!mpack_reader_ensure(reader, 1))
  2177. return 0;
  2178. uint8_t type = mpack_load_u8(reader->data);
  2179. // unfortunately, by far the fastest way to parse a tag is to switch
  2180. // on the first byte, and to explicitly list every possible byte. so for
  2181. // infix types, the list of cases is quite large.
  2182. //
  2183. // in size-optimized builds, we switch on the top four bits first to
  2184. // handle most infix types with a smaller jump table to save space.
  2185. #if MPACK_OPTIMIZE_FOR_SIZE
  2186. switch (type >> 4) {
  2187. // positive fixnum
  2188. case 0x0: case 0x1: case 0x2: case 0x3:
  2189. case 0x4: case 0x5: case 0x6: case 0x7:
  2190. *tag = mpack_tag_make_uint(type);
  2191. return 1;
  2192. // negative fixnum
  2193. case 0xe: case 0xf:
  2194. *tag = mpack_tag_make_int((int8_t)type);
  2195. return 1;
  2196. // fixmap
  2197. case 0x8:
  2198. *tag = mpack_tag_make_map(type & ~0xf0u);
  2199. return 1;
  2200. // fixarray
  2201. case 0x9:
  2202. *tag = mpack_tag_make_array(type & ~0xf0u);
  2203. return 1;
  2204. // fixstr
  2205. case 0xa: case 0xb:
  2206. *tag = mpack_tag_make_str(type & ~0xe0u);
  2207. return 1;
  2208. // not one of the common infix types
  2209. default:
  2210. break;
  2211. }
  2212. #endif
  2213. // handle individual type tags
  2214. switch (type) {
  2215. #if !MPACK_OPTIMIZE_FOR_SIZE
  2216. // positive fixnum
  2217. case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
  2218. case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
  2219. case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
  2220. case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
  2221. case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
  2222. case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
  2223. case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
  2224. case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
  2225. case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
  2226. case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
  2227. case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
  2228. case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
  2229. case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
  2230. case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
  2231. case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
  2232. case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
  2233. *tag = mpack_tag_make_uint(type);
  2234. return 1;
  2235. // negative fixnum
  2236. case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
  2237. case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
  2238. case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
  2239. case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
  2240. *tag = mpack_tag_make_int((int8_t)type);
  2241. return 1;
  2242. // fixmap
  2243. case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
  2244. case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
  2245. *tag = mpack_tag_make_map(type & ~0xf0u);
  2246. return 1;
  2247. // fixarray
  2248. case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
  2249. case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
  2250. *tag = mpack_tag_make_array(type & ~0xf0u);
  2251. return 1;
  2252. // fixstr
  2253. case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
  2254. case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
  2255. case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
  2256. case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
  2257. *tag = mpack_tag_make_str(type & ~0xe0u);
  2258. return 1;
  2259. #endif
  2260. // nil
  2261. case 0xc0:
  2262. *tag = mpack_tag_make_nil();
  2263. return 1;
  2264. // bool
  2265. case 0xc2: case 0xc3:
  2266. *tag = mpack_tag_make_bool((bool)(type & 1));
  2267. return 1;
  2268. // bin8
  2269. case 0xc4:
  2270. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_BIN8))
  2271. return 0;
  2272. *tag = mpack_tag_make_bin(mpack_load_u8(reader->data + 1));
  2273. return MPACK_TAG_SIZE_BIN8;
  2274. // bin16
  2275. case 0xc5:
  2276. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_BIN16))
  2277. return 0;
  2278. *tag = mpack_tag_make_bin(mpack_load_u16(reader->data + 1));
  2279. return MPACK_TAG_SIZE_BIN16;
  2280. // bin32
  2281. case 0xc6:
  2282. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_BIN32))
  2283. return 0;
  2284. *tag = mpack_tag_make_bin(mpack_load_u32(reader->data + 1));
  2285. return MPACK_TAG_SIZE_BIN32;
  2286. #if MPACK_EXTENSIONS
  2287. // ext8
  2288. case 0xc7:
  2289. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_EXT8))
  2290. return 0;
  2291. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 2), mpack_load_u8(reader->data + 1));
  2292. return MPACK_TAG_SIZE_EXT8;
  2293. // ext16
  2294. case 0xc8:
  2295. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_EXT16))
  2296. return 0;
  2297. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 3), mpack_load_u16(reader->data + 1));
  2298. return MPACK_TAG_SIZE_EXT16;
  2299. // ext32
  2300. case 0xc9:
  2301. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_EXT32))
  2302. return 0;
  2303. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 5), mpack_load_u32(reader->data + 1));
  2304. return MPACK_TAG_SIZE_EXT32;
  2305. #endif
  2306. // float
  2307. case 0xca:
  2308. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_FLOAT))
  2309. return 0;
  2310. *tag = mpack_tag_make_float(mpack_load_float(reader->data + 1));
  2311. return MPACK_TAG_SIZE_FLOAT;
  2312. // double
  2313. case 0xcb:
  2314. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_DOUBLE))
  2315. return 0;
  2316. *tag = mpack_tag_make_double(mpack_load_double(reader->data + 1));
  2317. return MPACK_TAG_SIZE_DOUBLE;
  2318. // uint8
  2319. case 0xcc:
  2320. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_U8))
  2321. return 0;
  2322. *tag = mpack_tag_make_uint(mpack_load_u8(reader->data + 1));
  2323. return MPACK_TAG_SIZE_U8;
  2324. // uint16
  2325. case 0xcd:
  2326. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_U16))
  2327. return 0;
  2328. *tag = mpack_tag_make_uint(mpack_load_u16(reader->data + 1));
  2329. return MPACK_TAG_SIZE_U16;
  2330. // uint32
  2331. case 0xce:
  2332. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_U32))
  2333. return 0;
  2334. *tag = mpack_tag_make_uint(mpack_load_u32(reader->data + 1));
  2335. return MPACK_TAG_SIZE_U32;
  2336. // uint64
  2337. case 0xcf:
  2338. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_U64))
  2339. return 0;
  2340. *tag = mpack_tag_make_uint(mpack_load_u64(reader->data + 1));
  2341. return MPACK_TAG_SIZE_U64;
  2342. // int8
  2343. case 0xd0:
  2344. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_I8))
  2345. return 0;
  2346. *tag = mpack_tag_make_int(mpack_load_i8(reader->data + 1));
  2347. return MPACK_TAG_SIZE_I8;
  2348. // int16
  2349. case 0xd1:
  2350. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_I16))
  2351. return 0;
  2352. *tag = mpack_tag_make_int(mpack_load_i16(reader->data + 1));
  2353. return MPACK_TAG_SIZE_I16;
  2354. // int32
  2355. case 0xd2:
  2356. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_I32))
  2357. return 0;
  2358. *tag = mpack_tag_make_int(mpack_load_i32(reader->data + 1));
  2359. return MPACK_TAG_SIZE_I32;
  2360. // int64
  2361. case 0xd3:
  2362. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_I64))
  2363. return 0;
  2364. *tag = mpack_tag_make_int(mpack_load_i64(reader->data + 1));
  2365. return MPACK_TAG_SIZE_I64;
  2366. #if MPACK_EXTENSIONS
  2367. // fixext1
  2368. case 0xd4:
  2369. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_FIXEXT1))
  2370. return 0;
  2371. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 1), 1);
  2372. return MPACK_TAG_SIZE_FIXEXT1;
  2373. // fixext2
  2374. case 0xd5:
  2375. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_FIXEXT2))
  2376. return 0;
  2377. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 1), 2);
  2378. return MPACK_TAG_SIZE_FIXEXT2;
  2379. // fixext4
  2380. case 0xd6:
  2381. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_FIXEXT4))
  2382. return 0;
  2383. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 1), 4);
  2384. return 2;
  2385. // fixext8
  2386. case 0xd7:
  2387. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_FIXEXT8))
  2388. return 0;
  2389. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 1), 8);
  2390. return MPACK_TAG_SIZE_FIXEXT8;
  2391. // fixext16
  2392. case 0xd8:
  2393. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_FIXEXT16))
  2394. return 0;
  2395. *tag = mpack_tag_make_ext(mpack_load_i8(reader->data + 1), 16);
  2396. return MPACK_TAG_SIZE_FIXEXT16;
  2397. #endif
  2398. // str8
  2399. case 0xd9:
  2400. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_STR8))
  2401. return 0;
  2402. *tag = mpack_tag_make_str(mpack_load_u8(reader->data + 1));
  2403. return MPACK_TAG_SIZE_STR8;
  2404. // str16
  2405. case 0xda:
  2406. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_STR16))
  2407. return 0;
  2408. *tag = mpack_tag_make_str(mpack_load_u16(reader->data + 1));
  2409. return MPACK_TAG_SIZE_STR16;
  2410. // str32
  2411. case 0xdb:
  2412. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_STR32))
  2413. return 0;
  2414. *tag = mpack_tag_make_str(mpack_load_u32(reader->data + 1));
  2415. return MPACK_TAG_SIZE_STR32;
  2416. // array16
  2417. case 0xdc:
  2418. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_ARRAY16))
  2419. return 0;
  2420. *tag = mpack_tag_make_array(mpack_load_u16(reader->data + 1));
  2421. return MPACK_TAG_SIZE_ARRAY16;
  2422. // array32
  2423. case 0xdd:
  2424. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_ARRAY32))
  2425. return 0;
  2426. *tag = mpack_tag_make_array(mpack_load_u32(reader->data + 1));
  2427. return MPACK_TAG_SIZE_ARRAY32;
  2428. // map16
  2429. case 0xde:
  2430. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_MAP16))
  2431. return 0;
  2432. *tag = mpack_tag_make_map(mpack_load_u16(reader->data + 1));
  2433. return MPACK_TAG_SIZE_MAP16;
  2434. // map32
  2435. case 0xdf:
  2436. if (!mpack_reader_ensure(reader, MPACK_TAG_SIZE_MAP32))
  2437. return 0;
  2438. *tag = mpack_tag_make_map(mpack_load_u32(reader->data + 1));
  2439. return MPACK_TAG_SIZE_MAP32;
  2440. // reserved
  2441. case 0xc1:
  2442. mpack_reader_flag_error(reader, mpack_error_invalid);
  2443. return 0;
  2444. #if !MPACK_EXTENSIONS
  2445. // ext
  2446. case 0xc7: // fallthrough
  2447. case 0xc8: // fallthrough
  2448. case 0xc9: // fallthrough
  2449. // fixext
  2450. case 0xd4: // fallthrough
  2451. case 0xd5: // fallthrough
  2452. case 0xd6: // fallthrough
  2453. case 0xd7: // fallthrough
  2454. case 0xd8:
  2455. mpack_reader_flag_error(reader, mpack_error_unsupported);
  2456. return 0;
  2457. #endif
  2458. #if MPACK_OPTIMIZE_FOR_SIZE
  2459. // any other bytes should have been handled by the infix switch
  2460. default:
  2461. break;
  2462. #endif
  2463. }
  2464. mpack_assert(0, "unreachable");
  2465. return 0;
  2466. }
  2467. mpack_tag_t mpack_read_tag(mpack_reader_t* reader) {
  2468. mpack_log("reading tag\n");
  2469. // make sure we can read a tag
  2470. if (mpack_reader_error(reader) != mpack_ok)
  2471. return mpack_tag_nil();
  2472. if (mpack_reader_track_element(reader) != mpack_ok)
  2473. return mpack_tag_nil();
  2474. mpack_tag_t tag = MPACK_TAG_ZERO;
  2475. size_t count = mpack_parse_tag(reader, &tag);
  2476. if (count == 0)
  2477. return mpack_tag_nil();
  2478. #if MPACK_READ_TRACKING
  2479. mpack_error_t track_error = mpack_ok;
  2480. switch (tag.type) {
  2481. case mpack_type_map:
  2482. case mpack_type_array:
  2483. track_error = mpack_track_push(&reader->track, tag.type, tag.v.n);
  2484. break;
  2485. #if MPACK_EXTENSIONS
  2486. case mpack_type_ext:
  2487. #endif
  2488. case mpack_type_str:
  2489. case mpack_type_bin:
  2490. track_error = mpack_track_push(&reader->track, tag.type, tag.v.l);
  2491. break;
  2492. default:
  2493. break;
  2494. }
  2495. if (track_error != mpack_ok) {
  2496. mpack_reader_flag_error(reader, track_error);
  2497. return mpack_tag_nil();
  2498. }
  2499. #endif
  2500. reader->data += count;
  2501. return tag;
  2502. }
  2503. mpack_tag_t mpack_peek_tag(mpack_reader_t* reader) {
  2504. mpack_log("peeking tag\n");
  2505. // make sure we can peek a tag
  2506. if (mpack_reader_error(reader) != mpack_ok)
  2507. return mpack_tag_nil();
  2508. if (mpack_reader_track_peek_element(reader) != mpack_ok)
  2509. return mpack_tag_nil();
  2510. mpack_tag_t tag = MPACK_TAG_ZERO;
  2511. if (mpack_parse_tag(reader, &tag) == 0)
  2512. return mpack_tag_nil();
  2513. return tag;
  2514. }
  2515. void mpack_discard(mpack_reader_t* reader) {
  2516. mpack_tag_t var = mpack_read_tag(reader);
  2517. if (mpack_reader_error(reader))
  2518. return;
  2519. switch (var.type) {
  2520. case mpack_type_str:
  2521. mpack_skip_bytes(reader, var.v.l);
  2522. mpack_done_str(reader);
  2523. break;
  2524. case mpack_type_bin:
  2525. mpack_skip_bytes(reader, var.v.l);
  2526. mpack_done_bin(reader);
  2527. break;
  2528. #if MPACK_EXTENSIONS
  2529. case mpack_type_ext:
  2530. mpack_skip_bytes(reader, var.v.l);
  2531. mpack_done_ext(reader);
  2532. break;
  2533. #endif
  2534. case mpack_type_array: {
  2535. for (; var.v.n > 0; --var.v.n) {
  2536. mpack_discard(reader);
  2537. if (mpack_reader_error(reader))
  2538. break;
  2539. }
  2540. mpack_done_array(reader);
  2541. break;
  2542. }
  2543. case mpack_type_map: {
  2544. for (; var.v.n > 0; --var.v.n) {
  2545. mpack_discard(reader);
  2546. mpack_discard(reader);
  2547. if (mpack_reader_error(reader))
  2548. break;
  2549. }
  2550. mpack_done_map(reader);
  2551. break;
  2552. }
  2553. default:
  2554. break;
  2555. }
  2556. }
  2557. #if MPACK_EXTENSIONS
  2558. mpack_timestamp_t mpack_read_timestamp(mpack_reader_t* reader, size_t size) {
  2559. mpack_timestamp_t timestamp = {0, 0};
  2560. if (size != 4 && size != 8 && size != 12) {
  2561. mpack_reader_flag_error(reader, mpack_error_invalid);
  2562. return timestamp;
  2563. }
  2564. char buf[12];
  2565. mpack_read_bytes(reader, buf, size);
  2566. mpack_done_ext(reader);
  2567. if (mpack_reader_error(reader) != mpack_ok)
  2568. return timestamp;
  2569. switch (size) {
  2570. case 4:
  2571. timestamp.seconds = (int64_t)(uint64_t)mpack_load_u32(buf);
  2572. break;
  2573. case 8: {
  2574. uint64_t packed = mpack_load_u64(buf);
  2575. timestamp.seconds = (int64_t)(packed & ((UINT64_C(1) << 34) - 1));
  2576. timestamp.nanoseconds = (uint32_t)(packed >> 34);
  2577. break;
  2578. }
  2579. case 12:
  2580. timestamp.nanoseconds = mpack_load_u32(buf);
  2581. timestamp.seconds = mpack_load_i64(buf + 4);
  2582. break;
  2583. default:
  2584. mpack_assert(false, "unreachable");
  2585. break;
  2586. }
  2587. if (timestamp.nanoseconds > MPACK_TIMESTAMP_NANOSECONDS_MAX) {
  2588. mpack_reader_flag_error(reader, mpack_error_invalid);
  2589. mpack_timestamp_t zero = {0, 0};
  2590. return zero;
  2591. }
  2592. return timestamp;
  2593. }
  2594. #endif
  2595. #if MPACK_READ_TRACKING
  2596. void mpack_done_type(mpack_reader_t* reader, mpack_type_t type) {
  2597. if (mpack_reader_error(reader) == mpack_ok)
  2598. mpack_reader_flag_if_error(reader, mpack_track_pop(&reader->track, type));
  2599. }
  2600. #endif
  2601. #if MPACK_DEBUG && MPACK_STDIO
  2602. static size_t mpack_print_read_prefix(mpack_reader_t* reader, size_t length, char* buffer, size_t buffer_size) {
  2603. if (length == 0)
  2604. return 0;
  2605. size_t read = (length < buffer_size) ? length : buffer_size;
  2606. mpack_read_bytes(reader, buffer, read);
  2607. if (mpack_reader_error(reader) != mpack_ok)
  2608. return 0;
  2609. mpack_skip_bytes(reader, length - read);
  2610. return read;
  2611. }
  2612. static void mpack_print_element(mpack_reader_t* reader, mpack_print_t* print, size_t depth) {
  2613. mpack_tag_t val = mpack_read_tag(reader);
  2614. if (mpack_reader_error(reader) != mpack_ok)
  2615. return;
  2616. // We read some bytes from bin and ext so we can print its prefix in hex.
  2617. char buffer[MPACK_PRINT_BYTE_COUNT];
  2618. size_t count = 0;
  2619. switch (val.type) {
  2620. case mpack_type_str:
  2621. mpack_print_append_cstr(print, "\"");
  2622. for (size_t i = 0; i < val.v.l; ++i) {
  2623. char c;
  2624. mpack_read_bytes(reader, &c, 1);
  2625. if (mpack_reader_error(reader) != mpack_ok)
  2626. return;
  2627. switch (c) {
  2628. case '\n': mpack_print_append_cstr(print, "\\n"); break;
  2629. case '\\': mpack_print_append_cstr(print, "\\\\"); break;
  2630. case '"': mpack_print_append_cstr(print, "\\\""); break;
  2631. default: mpack_print_append(print, &c, 1); break;
  2632. }
  2633. }
  2634. mpack_print_append_cstr(print, "\"");
  2635. mpack_done_str(reader);
  2636. return;
  2637. case mpack_type_array:
  2638. mpack_print_append_cstr(print, "[\n");
  2639. for (size_t i = 0; i < val.v.n; ++i) {
  2640. for (size_t j = 0; j < depth + 1; ++j)
  2641. mpack_print_append_cstr(print, " ");
  2642. mpack_print_element(reader, print, depth + 1);
  2643. if (mpack_reader_error(reader) != mpack_ok)
  2644. return;
  2645. if (i != val.v.n - 1)
  2646. mpack_print_append_cstr(print, ",");
  2647. mpack_print_append_cstr(print, "\n");
  2648. }
  2649. for (size_t i = 0; i < depth; ++i)
  2650. mpack_print_append_cstr(print, " ");
  2651. mpack_print_append_cstr(print, "]");
  2652. mpack_done_array(reader);
  2653. return;
  2654. case mpack_type_map:
  2655. mpack_print_append_cstr(print, "{\n");
  2656. for (size_t i = 0; i < val.v.n; ++i) {
  2657. for (size_t j = 0; j < depth + 1; ++j)
  2658. mpack_print_append_cstr(print, " ");
  2659. mpack_print_element(reader, print, depth + 1);
  2660. if (mpack_reader_error(reader) != mpack_ok)
  2661. return;
  2662. mpack_print_append_cstr(print, ": ");
  2663. mpack_print_element(reader, print, depth + 1);
  2664. if (mpack_reader_error(reader) != mpack_ok)
  2665. return;
  2666. if (i != val.v.n - 1)
  2667. mpack_print_append_cstr(print, ",");
  2668. mpack_print_append_cstr(print, "\n");
  2669. }
  2670. for (size_t i = 0; i < depth; ++i)
  2671. mpack_print_append_cstr(print, " ");
  2672. mpack_print_append_cstr(print, "}");
  2673. mpack_done_map(reader);
  2674. return;
  2675. // The above cases return so as not to print a pseudo-json value. The
  2676. // below cases break and print pseudo-json.
  2677. case mpack_type_bin:
  2678. count = mpack_print_read_prefix(reader, mpack_tag_bin_length(&val), buffer, sizeof(buffer));
  2679. mpack_done_bin(reader);
  2680. break;
  2681. #if MPACK_EXTENSIONS
  2682. case mpack_type_ext:
  2683. count = mpack_print_read_prefix(reader, mpack_tag_ext_length(&val), buffer, sizeof(buffer));
  2684. mpack_done_ext(reader);
  2685. break;
  2686. #endif
  2687. default:
  2688. break;
  2689. }
  2690. char buf[256];
  2691. mpack_tag_debug_pseudo_json(val, buf, sizeof(buf), buffer, count);
  2692. mpack_print_append_cstr(print, buf);
  2693. }
  2694. static void mpack_print_and_destroy(mpack_reader_t* reader, mpack_print_t* print, size_t depth) {
  2695. for (size_t i = 0; i < depth; ++i)
  2696. mpack_print_append_cstr(print, " ");
  2697. mpack_print_element(reader, print, depth);
  2698. size_t remaining = mpack_reader_remaining(reader, NULL);
  2699. char buf[256];
  2700. if (mpack_reader_destroy(reader) != mpack_ok) {
  2701. mpack_snprintf(buf, sizeof(buf), "\n<mpack parsing error %s>", mpack_error_to_string(mpack_reader_error(reader)));
  2702. buf[sizeof(buf) - 1] = '\0';
  2703. mpack_print_append_cstr(print, buf);
  2704. } else if (remaining > 0) {
  2705. mpack_snprintf(buf, sizeof(buf), "\n<%i extra bytes at end of message>", (int)remaining);
  2706. buf[sizeof(buf) - 1] = '\0';
  2707. mpack_print_append_cstr(print, buf);
  2708. }
  2709. }
  2710. static void mpack_print_data(const char* data, size_t len, mpack_print_t* print, size_t depth) {
  2711. mpack_reader_t reader;
  2712. mpack_reader_init_data(&reader, data, len);
  2713. mpack_print_and_destroy(&reader, print, depth);
  2714. }
  2715. void mpack_print_data_to_buffer(const char* data, size_t data_size, char* buffer, size_t buffer_size) {
  2716. if (buffer_size == 0) {
  2717. mpack_assert(false, "buffer size is zero!");
  2718. return;
  2719. }
  2720. mpack_print_t print;
  2721. mpack_memset(&print, 0, sizeof(print));
  2722. print.buffer = buffer;
  2723. print.size = buffer_size;
  2724. mpack_print_data(data, data_size, &print, 0);
  2725. mpack_print_append(&print, "", 1); // null-terminator
  2726. mpack_print_flush(&print);
  2727. // we always make sure there's a null-terminator at the end of the buffer
  2728. // in case we ran out of space.
  2729. print.buffer[print.size - 1] = '\0';
  2730. }
  2731. void mpack_print_data_to_callback(const char* data, size_t size, mpack_print_callback_t callback, void* context) {
  2732. char buffer[1024];
  2733. mpack_print_t print;
  2734. mpack_memset(&print, 0, sizeof(print));
  2735. print.buffer = buffer;
  2736. print.size = sizeof(buffer);
  2737. print.callback = callback;
  2738. print.context = context;
  2739. mpack_print_data(data, size, &print, 0);
  2740. mpack_print_flush(&print);
  2741. }
  2742. void mpack_print_data_to_file(const char* data, size_t len, FILE* file) {
  2743. mpack_assert(data != NULL, "data is NULL");
  2744. mpack_assert(file != NULL, "file is NULL");
  2745. char buffer[1024];
  2746. mpack_print_t print;
  2747. mpack_memset(&print, 0, sizeof(print));
  2748. print.buffer = buffer;
  2749. print.size = sizeof(buffer);
  2750. print.callback = &mpack_print_file_callback;
  2751. print.context = file;
  2752. mpack_print_data(data, len, &print, 2);
  2753. mpack_print_append_cstr(&print, "\n");
  2754. mpack_print_flush(&print);
  2755. }
  2756. void mpack_print_stdfile_to_callback(FILE* file, mpack_print_callback_t callback, void* context) {
  2757. char buffer[1024];
  2758. mpack_print_t print;
  2759. mpack_memset(&print, 0, sizeof(print));
  2760. print.buffer = buffer;
  2761. print.size = sizeof(buffer);
  2762. print.callback = callback;
  2763. print.context = context;
  2764. mpack_reader_t reader;
  2765. mpack_reader_init_stdfile(&reader, file, false);
  2766. mpack_print_and_destroy(&reader, &print, 0);
  2767. mpack_print_flush(&print);
  2768. }
  2769. #endif
  2770. #endif
  2771. /* mpack/mpack-expect.c.c */
  2772. #define MPACK_INTERNAL 1
  2773. /* #include "mpack-expect.h" */
  2774. #if MPACK_EXPECT
  2775. // Helpers
  2776. MPACK_STATIC_INLINE uint8_t mpack_expect_native_u8(mpack_reader_t* reader) {
  2777. if (mpack_reader_error(reader) != mpack_ok)
  2778. return 0;
  2779. uint8_t type;
  2780. if (!mpack_reader_ensure(reader, sizeof(type)))
  2781. return 0;
  2782. type = mpack_load_u8(reader->data);
  2783. reader->data += sizeof(type);
  2784. return type;
  2785. }
  2786. #if !MPACK_OPTIMIZE_FOR_SIZE
  2787. MPACK_STATIC_INLINE uint16_t mpack_expect_native_u16(mpack_reader_t* reader) {
  2788. if (mpack_reader_error(reader) != mpack_ok)
  2789. return 0;
  2790. uint16_t type;
  2791. if (!mpack_reader_ensure(reader, sizeof(type)))
  2792. return 0;
  2793. type = mpack_load_u16(reader->data);
  2794. reader->data += sizeof(type);
  2795. return type;
  2796. }
  2797. MPACK_STATIC_INLINE uint32_t mpack_expect_native_u32(mpack_reader_t* reader) {
  2798. if (mpack_reader_error(reader) != mpack_ok)
  2799. return 0;
  2800. uint32_t type;
  2801. if (!mpack_reader_ensure(reader, sizeof(type)))
  2802. return 0;
  2803. type = mpack_load_u32(reader->data);
  2804. reader->data += sizeof(type);
  2805. return type;
  2806. }
  2807. #endif
  2808. MPACK_STATIC_INLINE uint8_t mpack_expect_type_byte(mpack_reader_t* reader) {
  2809. mpack_reader_track_element(reader);
  2810. return mpack_expect_native_u8(reader);
  2811. }
  2812. // Basic Number Functions
  2813. uint8_t mpack_expect_u8(mpack_reader_t* reader) {
  2814. mpack_tag_t var = mpack_read_tag(reader);
  2815. if (var.type == mpack_type_uint) {
  2816. if (var.v.u <= UINT8_MAX)
  2817. return (uint8_t)var.v.u;
  2818. } else if (var.type == mpack_type_int) {
  2819. if (var.v.i >= 0 && var.v.i <= UINT8_MAX)
  2820. return (uint8_t)var.v.i;
  2821. }
  2822. mpack_reader_flag_error(reader, mpack_error_type);
  2823. return 0;
  2824. }
  2825. uint16_t mpack_expect_u16(mpack_reader_t* reader) {
  2826. mpack_tag_t var = mpack_read_tag(reader);
  2827. if (var.type == mpack_type_uint) {
  2828. if (var.v.u <= UINT16_MAX)
  2829. return (uint16_t)var.v.u;
  2830. } else if (var.type == mpack_type_int) {
  2831. if (var.v.i >= 0 && var.v.i <= UINT16_MAX)
  2832. return (uint16_t)var.v.i;
  2833. }
  2834. mpack_reader_flag_error(reader, mpack_error_type);
  2835. return 0;
  2836. }
  2837. uint32_t mpack_expect_u32(mpack_reader_t* reader) {
  2838. mpack_tag_t var = mpack_read_tag(reader);
  2839. if (var.type == mpack_type_uint) {
  2840. if (var.v.u <= UINT32_MAX)
  2841. return (uint32_t)var.v.u;
  2842. } else if (var.type == mpack_type_int) {
  2843. if (var.v.i >= 0 && var.v.i <= UINT32_MAX)
  2844. return (uint32_t)var.v.i;
  2845. }
  2846. mpack_reader_flag_error(reader, mpack_error_type);
  2847. return 0;
  2848. }
  2849. uint64_t mpack_expect_u64(mpack_reader_t* reader) {
  2850. mpack_tag_t var = mpack_read_tag(reader);
  2851. if (var.type == mpack_type_uint) {
  2852. return var.v.u;
  2853. } else if (var.type == mpack_type_int) {
  2854. if (var.v.i >= 0)
  2855. return (uint64_t)var.v.i;
  2856. }
  2857. mpack_reader_flag_error(reader, mpack_error_type);
  2858. return 0;
  2859. }
  2860. int8_t mpack_expect_i8(mpack_reader_t* reader) {
  2861. mpack_tag_t var = mpack_read_tag(reader);
  2862. if (var.type == mpack_type_uint) {
  2863. if (var.v.u <= INT8_MAX)
  2864. return (int8_t)var.v.u;
  2865. } else if (var.type == mpack_type_int) {
  2866. if (var.v.i >= INT8_MIN && var.v.i <= INT8_MAX)
  2867. return (int8_t)var.v.i;
  2868. }
  2869. mpack_reader_flag_error(reader, mpack_error_type);
  2870. return 0;
  2871. }
  2872. int16_t mpack_expect_i16(mpack_reader_t* reader) {
  2873. mpack_tag_t var = mpack_read_tag(reader);
  2874. if (var.type == mpack_type_uint) {
  2875. if (var.v.u <= INT16_MAX)
  2876. return (int16_t)var.v.u;
  2877. } else if (var.type == mpack_type_int) {
  2878. if (var.v.i >= INT16_MIN && var.v.i <= INT16_MAX)
  2879. return (int16_t)var.v.i;
  2880. }
  2881. mpack_reader_flag_error(reader, mpack_error_type);
  2882. return 0;
  2883. }
  2884. int32_t mpack_expect_i32(mpack_reader_t* reader) {
  2885. mpack_tag_t var = mpack_read_tag(reader);
  2886. if (var.type == mpack_type_uint) {
  2887. if (var.v.u <= INT32_MAX)
  2888. return (int32_t)var.v.u;
  2889. } else if (var.type == mpack_type_int) {
  2890. if (var.v.i >= INT32_MIN && var.v.i <= INT32_MAX)
  2891. return (int32_t)var.v.i;
  2892. }
  2893. mpack_reader_flag_error(reader, mpack_error_type);
  2894. return 0;
  2895. }
  2896. int64_t mpack_expect_i64(mpack_reader_t* reader) {
  2897. mpack_tag_t var = mpack_read_tag(reader);
  2898. if (var.type == mpack_type_uint) {
  2899. if (var.v.u <= INT64_MAX)
  2900. return (int64_t)var.v.u;
  2901. } else if (var.type == mpack_type_int) {
  2902. return var.v.i;
  2903. }
  2904. mpack_reader_flag_error(reader, mpack_error_type);
  2905. return 0;
  2906. }
  2907. float mpack_expect_float(mpack_reader_t* reader) {
  2908. mpack_tag_t var = mpack_read_tag(reader);
  2909. if (var.type == mpack_type_uint)
  2910. return (float)var.v.u;
  2911. else if (var.type == mpack_type_int)
  2912. return (float)var.v.i;
  2913. else if (var.type == mpack_type_float)
  2914. return var.v.f;
  2915. else if (var.type == mpack_type_double)
  2916. return (float)var.v.d;
  2917. mpack_reader_flag_error(reader, mpack_error_type);
  2918. return 0.0f;
  2919. }
  2920. double mpack_expect_double(mpack_reader_t* reader) {
  2921. mpack_tag_t var = mpack_read_tag(reader);
  2922. if (var.type == mpack_type_uint)
  2923. return (double)var.v.u;
  2924. else if (var.type == mpack_type_int)
  2925. return (double)var.v.i;
  2926. else if (var.type == mpack_type_float)
  2927. return (double)var.v.f;
  2928. else if (var.type == mpack_type_double)
  2929. return var.v.d;
  2930. mpack_reader_flag_error(reader, mpack_error_type);
  2931. return 0.0;
  2932. }
  2933. float mpack_expect_float_strict(mpack_reader_t* reader) {
  2934. mpack_tag_t var = mpack_read_tag(reader);
  2935. if (var.type == mpack_type_float)
  2936. return var.v.f;
  2937. mpack_reader_flag_error(reader, mpack_error_type);
  2938. return 0.0f;
  2939. }
  2940. double mpack_expect_double_strict(mpack_reader_t* reader) {
  2941. mpack_tag_t var = mpack_read_tag(reader);
  2942. if (var.type == mpack_type_float)
  2943. return (double)var.v.f;
  2944. else if (var.type == mpack_type_double)
  2945. return var.v.d;
  2946. mpack_reader_flag_error(reader, mpack_error_type);
  2947. return 0.0;
  2948. }
  2949. // Ranged Number Functions
  2950. //
  2951. // All ranged functions are identical other than the type, so we
  2952. // define their content with a macro. The prototypes are still written
  2953. // out in full to support ctags/IDE tools.
  2954. #define MPACK_EXPECT_RANGE_IMPL(name, type_t) \
  2955. \
  2956. /* make sure the range is sensible */ \
  2957. mpack_assert(min_value <= max_value, \
  2958. "min_value %i must be less than or equal to max_value %i", \
  2959. min_value, max_value); \
  2960. \
  2961. /* read the value */ \
  2962. type_t val = mpack_expect_##name(reader); \
  2963. if (mpack_reader_error(reader) != mpack_ok) \
  2964. return min_value; \
  2965. \
  2966. /* make sure it fits */ \
  2967. if (val < min_value || val > max_value) { \
  2968. mpack_reader_flag_error(reader, mpack_error_type); \
  2969. return min_value; \
  2970. } \
  2971. \
  2972. return val;
  2973. 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)}
  2974. 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)}
  2975. 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)}
  2976. 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)}
  2977. 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)}
  2978. 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)}
  2979. 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)}
  2980. 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)}
  2981. float mpack_expect_float_range(mpack_reader_t* reader, float min_value, float max_value) {MPACK_EXPECT_RANGE_IMPL(float, float)}
  2982. double mpack_expect_double_range(mpack_reader_t* reader, double min_value, double max_value) {MPACK_EXPECT_RANGE_IMPL(double, double)}
  2983. 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)}
  2984. 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)}
  2985. // Matching Number Functions
  2986. void mpack_expect_uint_match(mpack_reader_t* reader, uint64_t value) {
  2987. if (mpack_expect_u64(reader) != value)
  2988. mpack_reader_flag_error(reader, mpack_error_type);
  2989. }
  2990. void mpack_expect_int_match(mpack_reader_t* reader, int64_t value) {
  2991. if (mpack_expect_i64(reader) != value)
  2992. mpack_reader_flag_error(reader, mpack_error_type);
  2993. }
  2994. // Other Basic Types
  2995. void mpack_expect_nil(mpack_reader_t* reader) {
  2996. if (mpack_expect_type_byte(reader) != 0xc0)
  2997. mpack_reader_flag_error(reader, mpack_error_type);
  2998. }
  2999. bool mpack_expect_bool(mpack_reader_t* reader) {
  3000. uint8_t type = mpack_expect_type_byte(reader);
  3001. if ((type & ~1) != 0xc2)
  3002. mpack_reader_flag_error(reader, mpack_error_type);
  3003. return (bool)(type & 1);
  3004. }
  3005. void mpack_expect_true(mpack_reader_t* reader) {
  3006. if (mpack_expect_bool(reader) != true)
  3007. mpack_reader_flag_error(reader, mpack_error_type);
  3008. }
  3009. void mpack_expect_false(mpack_reader_t* reader) {
  3010. if (mpack_expect_bool(reader) != false)
  3011. mpack_reader_flag_error(reader, mpack_error_type);
  3012. }
  3013. #if MPACK_EXTENSIONS
  3014. mpack_timestamp_t mpack_expect_timestamp(mpack_reader_t* reader) {
  3015. mpack_timestamp_t zero = {0, 0};
  3016. mpack_tag_t tag = mpack_read_tag(reader);
  3017. if (tag.type != mpack_type_ext) {
  3018. mpack_reader_flag_error(reader, mpack_error_type);
  3019. return zero;
  3020. }
  3021. if (mpack_tag_ext_exttype(&tag) != MPACK_EXTTYPE_TIMESTAMP) {
  3022. mpack_reader_flag_error(reader, mpack_error_type);
  3023. return zero;
  3024. }
  3025. return mpack_read_timestamp(reader, mpack_tag_ext_length(&tag));
  3026. }
  3027. int64_t mpack_expect_timestamp_truncate(mpack_reader_t* reader) {
  3028. return mpack_expect_timestamp(reader).seconds;
  3029. }
  3030. #endif
  3031. // Compound Types
  3032. uint32_t mpack_expect_map(mpack_reader_t* reader) {
  3033. mpack_tag_t var = mpack_read_tag(reader);
  3034. if (var.type == mpack_type_map)
  3035. return var.v.n;
  3036. mpack_reader_flag_error(reader, mpack_error_type);
  3037. return 0;
  3038. }
  3039. void mpack_expect_map_match(mpack_reader_t* reader, uint32_t count) {
  3040. if (mpack_expect_map(reader) != count)
  3041. mpack_reader_flag_error(reader, mpack_error_type);
  3042. }
  3043. bool mpack_expect_map_or_nil(mpack_reader_t* reader, uint32_t* count) {
  3044. mpack_assert(count != NULL, "count cannot be NULL");
  3045. mpack_tag_t var = mpack_read_tag(reader);
  3046. if (var.type == mpack_type_nil) {
  3047. *count = 0;
  3048. return false;
  3049. }
  3050. if (var.type == mpack_type_map) {
  3051. *count = var.v.n;
  3052. return true;
  3053. }
  3054. mpack_reader_flag_error(reader, mpack_error_type);
  3055. *count = 0;
  3056. return false;
  3057. }
  3058. bool mpack_expect_map_max_or_nil(mpack_reader_t* reader, uint32_t max_count, uint32_t* count) {
  3059. mpack_assert(count != NULL, "count cannot be NULL");
  3060. bool has_map = mpack_expect_map_or_nil(reader, count);
  3061. if (has_map && *count > max_count) {
  3062. *count = 0;
  3063. mpack_reader_flag_error(reader, mpack_error_type);
  3064. return false;
  3065. }
  3066. return has_map;
  3067. }
  3068. uint32_t mpack_expect_array(mpack_reader_t* reader) {
  3069. mpack_tag_t var = mpack_read_tag(reader);
  3070. if (var.type == mpack_type_array)
  3071. return var.v.n;
  3072. mpack_reader_flag_error(reader, mpack_error_type);
  3073. return 0;
  3074. }
  3075. void mpack_expect_array_match(mpack_reader_t* reader, uint32_t count) {
  3076. if (mpack_expect_array(reader) != count)
  3077. mpack_reader_flag_error(reader, mpack_error_type);
  3078. }
  3079. bool mpack_expect_array_or_nil(mpack_reader_t* reader, uint32_t* count) {
  3080. mpack_assert(count != NULL, "count cannot be NULL");
  3081. mpack_tag_t var = mpack_read_tag(reader);
  3082. if (var.type == mpack_type_nil) {
  3083. *count = 0;
  3084. return false;
  3085. }
  3086. if (var.type == mpack_type_array) {
  3087. *count = var.v.n;
  3088. return true;
  3089. }
  3090. mpack_reader_flag_error(reader, mpack_error_type);
  3091. *count = 0;
  3092. return false;
  3093. }
  3094. bool mpack_expect_array_max_or_nil(mpack_reader_t* reader, uint32_t max_count, uint32_t* count) {
  3095. mpack_assert(count != NULL, "count cannot be NULL");
  3096. bool has_array = mpack_expect_array_or_nil(reader, count);
  3097. if (has_array && *count > max_count) {
  3098. *count = 0;
  3099. mpack_reader_flag_error(reader, mpack_error_type);
  3100. return false;
  3101. }
  3102. return has_array;
  3103. }
  3104. #ifdef MPACK_MALLOC
  3105. 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) {
  3106. mpack_assert(out_count != NULL, "out_count cannot be NULL");
  3107. *out_count = 0;
  3108. uint32_t count;
  3109. bool has_array = true;
  3110. if (allow_nil)
  3111. has_array = mpack_expect_array_max_or_nil(reader, max_count, &count);
  3112. else
  3113. count = mpack_expect_array_max(reader, max_count);
  3114. if (mpack_reader_error(reader))
  3115. return NULL;
  3116. // size 0 is not an error; we return NULL for no elements.
  3117. if (count == 0) {
  3118. // we call mpack_done_array() automatically ONLY if we are using
  3119. // the _or_nil variant. this is the only way to allow nil and empty
  3120. // to work the same way.
  3121. if (allow_nil && has_array)
  3122. mpack_done_array(reader);
  3123. return NULL;
  3124. }
  3125. void* p = MPACK_MALLOC(element_size * count);
  3126. if (p == NULL) {
  3127. mpack_reader_flag_error(reader, mpack_error_memory);
  3128. return NULL;
  3129. }
  3130. *out_count = count;
  3131. return p;
  3132. }
  3133. #endif
  3134. // Str, Bin and Ext Functions
  3135. uint32_t mpack_expect_str(mpack_reader_t* reader) {
  3136. #if MPACK_OPTIMIZE_FOR_SIZE
  3137. mpack_tag_t var = mpack_read_tag(reader);
  3138. if (var.type == mpack_type_str)
  3139. return var.v.l;
  3140. mpack_reader_flag_error(reader, mpack_error_type);
  3141. return 0;
  3142. #else
  3143. uint8_t type = mpack_expect_type_byte(reader);
  3144. uint32_t count;
  3145. if ((type >> 5) == 5) {
  3146. count = type & (uint8_t)~0xe0;
  3147. } else if (type == 0xd9) {
  3148. count = mpack_expect_native_u8(reader);
  3149. } else if (type == 0xda) {
  3150. count = mpack_expect_native_u16(reader);
  3151. } else if (type == 0xdb) {
  3152. count = mpack_expect_native_u32(reader);
  3153. } else {
  3154. mpack_reader_flag_error(reader, mpack_error_type);
  3155. return 0;
  3156. }
  3157. #if MPACK_READ_TRACKING
  3158. mpack_reader_flag_if_error(reader, mpack_track_push(&reader->track, mpack_type_str, count));
  3159. #endif
  3160. return count;
  3161. #endif
  3162. }
  3163. size_t mpack_expect_str_buf(mpack_reader_t* reader, char* buf, size_t bufsize) {
  3164. mpack_assert(buf != NULL, "buf cannot be NULL");
  3165. size_t length = mpack_expect_str(reader);
  3166. if (mpack_reader_error(reader))
  3167. return 0;
  3168. if (length > bufsize) {
  3169. mpack_reader_flag_error(reader, mpack_error_too_big);
  3170. return 0;
  3171. }
  3172. mpack_read_bytes(reader, buf, length);
  3173. if (mpack_reader_error(reader))
  3174. return 0;
  3175. mpack_done_str(reader);
  3176. return length;
  3177. }
  3178. size_t mpack_expect_utf8(mpack_reader_t* reader, char* buf, size_t size) {
  3179. mpack_assert(buf != NULL, "buf cannot be NULL");
  3180. size_t length = mpack_expect_str_buf(reader, buf, size);
  3181. if (!mpack_utf8_check(buf, length)) {
  3182. mpack_reader_flag_error(reader, mpack_error_type);
  3183. return 0;
  3184. }
  3185. return length;
  3186. }
  3187. uint32_t mpack_expect_bin(mpack_reader_t* reader) {
  3188. mpack_tag_t var = mpack_read_tag(reader);
  3189. if (var.type == mpack_type_bin)
  3190. return var.v.l;
  3191. mpack_reader_flag_error(reader, mpack_error_type);
  3192. return 0;
  3193. }
  3194. size_t mpack_expect_bin_buf(mpack_reader_t* reader, char* buf, size_t bufsize) {
  3195. mpack_assert(buf != NULL, "buf cannot be NULL");
  3196. size_t binsize = mpack_expect_bin(reader);
  3197. if (mpack_reader_error(reader))
  3198. return 0;
  3199. if (binsize > bufsize) {
  3200. mpack_reader_flag_error(reader, mpack_error_too_big);
  3201. return 0;
  3202. }
  3203. mpack_read_bytes(reader, buf, binsize);
  3204. if (mpack_reader_error(reader))
  3205. return 0;
  3206. mpack_done_bin(reader);
  3207. return binsize;
  3208. }
  3209. #if MPACK_EXTENSIONS
  3210. uint32_t mpack_expect_ext(mpack_reader_t* reader, int8_t* type) {
  3211. mpack_tag_t var = mpack_read_tag(reader);
  3212. if (var.type == mpack_type_ext) {
  3213. *type = mpack_tag_ext_exttype(&var);
  3214. return mpack_tag_ext_length(&var);
  3215. }
  3216. *type = 0;
  3217. mpack_reader_flag_error(reader, mpack_error_type);
  3218. return 0;
  3219. }
  3220. size_t mpack_expect_ext_buf(mpack_reader_t* reader, int8_t* type, char* buf, size_t bufsize) {
  3221. mpack_assert(buf != NULL, "buf cannot be NULL");
  3222. size_t extsize = mpack_expect_ext(reader, type);
  3223. if (mpack_reader_error(reader))
  3224. return 0;
  3225. if (extsize > bufsize) {
  3226. *type = 0;
  3227. mpack_reader_flag_error(reader, mpack_error_too_big);
  3228. return 0;
  3229. }
  3230. mpack_read_bytes(reader, buf, extsize);
  3231. if (mpack_reader_error(reader)) {
  3232. *type = 0;
  3233. return 0;
  3234. }
  3235. mpack_done_ext(reader);
  3236. return extsize;
  3237. }
  3238. #endif
  3239. void mpack_expect_cstr(mpack_reader_t* reader, char* buf, size_t bufsize) {
  3240. uint32_t length = mpack_expect_str(reader);
  3241. mpack_read_cstr(reader, buf, bufsize, length);
  3242. mpack_done_str(reader);
  3243. }
  3244. void mpack_expect_utf8_cstr(mpack_reader_t* reader, char* buf, size_t bufsize) {
  3245. uint32_t length = mpack_expect_str(reader);
  3246. mpack_read_utf8_cstr(reader, buf, bufsize, length);
  3247. mpack_done_str(reader);
  3248. }
  3249. #ifdef MPACK_MALLOC
  3250. static char* mpack_expect_cstr_alloc_unchecked(mpack_reader_t* reader, size_t maxsize, size_t* out_length) {
  3251. mpack_assert(out_length != NULL, "out_length cannot be NULL");
  3252. *out_length = 0;
  3253. // make sure argument makes sense
  3254. if (maxsize < 1) {
  3255. mpack_break("maxsize is zero; you must have room for at least a null-terminator");
  3256. mpack_reader_flag_error(reader, mpack_error_bug);
  3257. return NULL;
  3258. }
  3259. if (maxsize > UINT32_MAX)
  3260. maxsize = UINT32_MAX;
  3261. size_t length = mpack_expect_str_max(reader, (uint32_t)maxsize - 1);
  3262. char* str = mpack_read_bytes_alloc_impl(reader, length, true);
  3263. mpack_done_str(reader);
  3264. if (str)
  3265. *out_length = length;
  3266. return str;
  3267. }
  3268. char* mpack_expect_cstr_alloc(mpack_reader_t* reader, size_t maxsize) {
  3269. size_t length;
  3270. char* str = mpack_expect_cstr_alloc_unchecked(reader, maxsize, &length);
  3271. if (str && !mpack_str_check_no_null(str, length)) {
  3272. MPACK_FREE(str);
  3273. mpack_reader_flag_error(reader, mpack_error_type);
  3274. return NULL;
  3275. }
  3276. return str;
  3277. }
  3278. char* mpack_expect_utf8_cstr_alloc(mpack_reader_t* reader, size_t maxsize) {
  3279. size_t length;
  3280. char* str = mpack_expect_cstr_alloc_unchecked(reader, maxsize, &length);
  3281. if (str && !mpack_utf8_check_no_null(str, length)) {
  3282. MPACK_FREE(str);
  3283. mpack_reader_flag_error(reader, mpack_error_type);
  3284. return NULL;
  3285. }
  3286. return str;
  3287. }
  3288. #endif
  3289. void mpack_expect_str_match(mpack_reader_t* reader, const char* str, size_t len) {
  3290. mpack_assert(str != NULL, "str cannot be NULL");
  3291. // expect a str the correct length
  3292. if (len > UINT32_MAX)
  3293. mpack_reader_flag_error(reader, mpack_error_type);
  3294. mpack_expect_str_length(reader, (uint32_t)len);
  3295. if (mpack_reader_error(reader))
  3296. return;
  3297. mpack_reader_track_bytes(reader, len);
  3298. // check each byte one by one (matched strings are likely to be very small)
  3299. for (; len > 0; --len) {
  3300. if (mpack_expect_native_u8(reader) != *str++) {
  3301. mpack_reader_flag_error(reader, mpack_error_type);
  3302. return;
  3303. }
  3304. }
  3305. mpack_done_str(reader);
  3306. }
  3307. void mpack_expect_tag(mpack_reader_t* reader, mpack_tag_t expected) {
  3308. mpack_tag_t actual = mpack_read_tag(reader);
  3309. if (!mpack_tag_equal(actual, expected))
  3310. mpack_reader_flag_error(reader, mpack_error_type);
  3311. }
  3312. #ifdef MPACK_MALLOC
  3313. char* mpack_expect_bin_alloc(mpack_reader_t* reader, size_t maxsize, size_t* size) {
  3314. mpack_assert(size != NULL, "size cannot be NULL");
  3315. *size = 0;
  3316. if (maxsize > UINT32_MAX)
  3317. maxsize = UINT32_MAX;
  3318. size_t length = mpack_expect_bin_max(reader, (uint32_t)maxsize);
  3319. if (mpack_reader_error(reader))
  3320. return NULL;
  3321. char* data = mpack_read_bytes_alloc(reader, length);
  3322. mpack_done_bin(reader);
  3323. if (data)
  3324. *size = length;
  3325. return data;
  3326. }
  3327. #endif
  3328. #if MPACK_EXTENSIONS && defined(MPACK_MALLOC)
  3329. char* mpack_expect_ext_alloc(mpack_reader_t* reader, int8_t* type, size_t maxsize, size_t* size) {
  3330. mpack_assert(size != NULL, "size cannot be NULL");
  3331. *size = 0;
  3332. if (maxsize > UINT32_MAX)
  3333. maxsize = UINT32_MAX;
  3334. size_t length = mpack_expect_ext_max(reader, type, (uint32_t)maxsize);
  3335. if (mpack_reader_error(reader))
  3336. return NULL;
  3337. char* data = mpack_read_bytes_alloc(reader, length);
  3338. mpack_done_ext(reader);
  3339. if (data) {
  3340. *size = length;
  3341. } else {
  3342. *type = 0;
  3343. }
  3344. return data;
  3345. }
  3346. #endif
  3347. size_t mpack_expect_enum(mpack_reader_t* reader, const char* strings[], size_t count) {
  3348. // read the string in-place
  3349. size_t keylen = mpack_expect_str(reader);
  3350. const char* key = mpack_read_bytes_inplace(reader, keylen);
  3351. mpack_done_str(reader);
  3352. if (mpack_reader_error(reader) != mpack_ok)
  3353. return count;
  3354. // find what key it matches
  3355. for (size_t i = 0; i < count; ++i) {
  3356. const char* other = strings[i];
  3357. size_t otherlen = mpack_strlen(other);
  3358. if (keylen == otherlen && mpack_memcmp(key, other, keylen) == 0)
  3359. return i;
  3360. }
  3361. // no matches
  3362. mpack_reader_flag_error(reader, mpack_error_type);
  3363. return count;
  3364. }
  3365. size_t mpack_expect_enum_optional(mpack_reader_t* reader, const char* strings[], size_t count) {
  3366. if (mpack_reader_error(reader) != mpack_ok)
  3367. return count;
  3368. mpack_assert(count != 0, "count cannot be zero; no strings are valid!");
  3369. mpack_assert(strings != NULL, "strings cannot be NULL");
  3370. // the key is only recognized if it is a string
  3371. if (mpack_peek_tag(reader).type != mpack_type_str) {
  3372. mpack_discard(reader);
  3373. return count;
  3374. }
  3375. // read the string in-place
  3376. size_t keylen = mpack_expect_str(reader);
  3377. const char* key = mpack_read_bytes_inplace(reader, keylen);
  3378. mpack_done_str(reader);
  3379. if (mpack_reader_error(reader) != mpack_ok)
  3380. return count;
  3381. // find what key it matches
  3382. for (size_t i = 0; i < count; ++i) {
  3383. const char* other = strings[i];
  3384. size_t otherlen = mpack_strlen(other);
  3385. if (keylen == otherlen && mpack_memcmp(key, other, keylen) == 0)
  3386. return i;
  3387. }
  3388. // no matches
  3389. return count;
  3390. }
  3391. size_t mpack_expect_key_uint(mpack_reader_t* reader, bool found[], size_t count) {
  3392. if (mpack_reader_error(reader) != mpack_ok)
  3393. return count;
  3394. if (count == 0) {
  3395. mpack_break("count cannot be zero; no keys are valid!");
  3396. mpack_reader_flag_error(reader, mpack_error_bug);
  3397. return count;
  3398. }
  3399. mpack_assert(found != NULL, "found cannot be NULL");
  3400. // the key is only recognized if it is an unsigned int
  3401. if (mpack_peek_tag(reader).type != mpack_type_uint) {
  3402. mpack_discard(reader);
  3403. return count;
  3404. }
  3405. // read the key
  3406. uint64_t value = mpack_expect_u64(reader);
  3407. if (mpack_reader_error(reader) != mpack_ok)
  3408. return count;
  3409. // unrecognized keys are fine, we just return count
  3410. if (value >= count)
  3411. return count;
  3412. // check if this key is a duplicate
  3413. if (found[value]) {
  3414. mpack_reader_flag_error(reader, mpack_error_invalid);
  3415. return count;
  3416. }
  3417. found[value] = true;
  3418. return (size_t)value;
  3419. }
  3420. size_t mpack_expect_key_cstr(mpack_reader_t* reader, const char* keys[], bool found[], size_t count) {
  3421. size_t i = mpack_expect_enum_optional(reader, keys, count);
  3422. // unrecognized keys are fine, we just return count
  3423. if (i == count)
  3424. return count;
  3425. // check if this key is a duplicate
  3426. mpack_assert(found != NULL, "found cannot be NULL");
  3427. if (found[i]) {
  3428. mpack_reader_flag_error(reader, mpack_error_invalid);
  3429. return count;
  3430. }
  3431. found[i] = true;
  3432. return i;
  3433. }
  3434. #endif
  3435. /* mpack/mpack-node.c.c */
  3436. #define MPACK_INTERNAL 1
  3437. /* #include "mpack-node.h" */
  3438. #if MPACK_NODE
  3439. MPACK_STATIC_INLINE const char* mpack_node_data_unchecked(mpack_node_t node) {
  3440. mpack_assert(mpack_node_error(node) == mpack_ok, "tree is in an error state!");
  3441. mpack_type_t type = node.data->type;
  3442. MPACK_UNUSED(type);
  3443. #if MPACK_EXTENSIONS
  3444. mpack_assert(type == mpack_type_str || type == mpack_type_bin || type == mpack_type_ext,
  3445. "node of type %i (%s) is not a data type!", type, mpack_type_to_string(type));
  3446. #else
  3447. mpack_assert(type == mpack_type_str || type == mpack_type_bin,
  3448. "node of type %i (%s) is not a data type!", type, mpack_type_to_string(type));
  3449. #endif
  3450. return node.tree->data + node.data->value.offset;
  3451. }
  3452. #if MPACK_EXTENSIONS
  3453. MPACK_STATIC_INLINE int8_t mpack_node_exttype_unchecked(mpack_node_t node) {
  3454. mpack_assert(mpack_node_error(node) == mpack_ok, "tree is in an error state!");
  3455. mpack_type_t type = node.data->type;
  3456. MPACK_UNUSED(type);
  3457. mpack_assert(type == mpack_type_ext, "node of type %i (%s) is not an ext type!",
  3458. type, mpack_type_to_string(type));
  3459. // the exttype of an ext node is stored in the byte preceding the data
  3460. return mpack_load_i8(mpack_node_data_unchecked(node) - 1);
  3461. }
  3462. #endif
  3463. /*
  3464. * Tree Parsing
  3465. */
  3466. #ifdef MPACK_MALLOC
  3467. // fix up the alloc size to make sure it exactly fits the
  3468. // maximum number of nodes it can contain (the allocator will
  3469. // waste it back anyway, but we round it down just in case)
  3470. #define MPACK_NODES_PER_PAGE \
  3471. ((MPACK_NODE_PAGE_SIZE - sizeof(mpack_tree_page_t)) / sizeof(mpack_node_data_t) + 1)
  3472. #define MPACK_PAGE_ALLOC_SIZE \
  3473. (sizeof(mpack_tree_page_t) + sizeof(mpack_node_data_t) * (MPACK_NODES_PER_PAGE - 1))
  3474. #endif
  3475. #ifdef MPACK_MALLOC
  3476. /*
  3477. * Fills the tree until we have at least enough bytes for the current node.
  3478. */
  3479. static bool mpack_tree_reserve_fill(mpack_tree_t* tree) {
  3480. mpack_assert(tree->parser.state == mpack_tree_parse_state_in_progress);
  3481. size_t bytes = tree->parser.current_node_reserved;
  3482. mpack_assert(bytes > tree->parser.possible_nodes_left,
  3483. "there are already enough bytes! call mpack_tree_ensure() instead.");
  3484. mpack_log("filling to reserve %i bytes\n", (int)bytes);
  3485. // if the necessary bytes would put us over the maximum tree
  3486. // size, fail right away.
  3487. // TODO: check for overflow?
  3488. if (tree->data_length + bytes > tree->max_size) {
  3489. mpack_tree_flag_error(tree, mpack_error_too_big);
  3490. return false;
  3491. }
  3492. // we'll need a read function to fetch more data. if there's
  3493. // no read function, the data should contain an entire message
  3494. // (or messages), so we flag it as invalid.
  3495. if (tree->read_fn == NULL) {
  3496. mpack_log("tree has no read function!\n");
  3497. mpack_tree_flag_error(tree, mpack_error_invalid);
  3498. return false;
  3499. }
  3500. // expand the buffer if needed
  3501. if (tree->data_length + bytes > tree->buffer_capacity) {
  3502. // TODO: check for overflow?
  3503. size_t new_capacity = (tree->buffer_capacity == 0) ? MPACK_BUFFER_SIZE : tree->buffer_capacity;
  3504. while (new_capacity < tree->data_length + bytes)
  3505. new_capacity *= 2;
  3506. if (new_capacity > tree->max_size)
  3507. new_capacity = tree->max_size;
  3508. mpack_log("expanding buffer from %i to %i\n", (int)tree->buffer_capacity, (int)new_capacity);
  3509. char* new_buffer;
  3510. if (tree->buffer == NULL)
  3511. new_buffer = (char*)MPACK_MALLOC(new_capacity);
  3512. else
  3513. new_buffer = (char*)mpack_realloc(tree->buffer, tree->data_length, new_capacity);
  3514. if (new_buffer == NULL) {
  3515. mpack_tree_flag_error(tree, mpack_error_memory);
  3516. return false;
  3517. }
  3518. tree->data = new_buffer;
  3519. tree->buffer = new_buffer;
  3520. tree->buffer_capacity = new_capacity;
  3521. }
  3522. // request as much data as possible, looping until we have
  3523. // all the data we need
  3524. do {
  3525. size_t read = tree->read_fn(tree, tree->buffer + tree->data_length, tree->buffer_capacity - tree->data_length);
  3526. // If the fill function encounters an error, it should flag an error on
  3527. // the tree.
  3528. if (mpack_tree_error(tree) != mpack_ok)
  3529. return false;
  3530. // We guard against fill functions that return -1 just in case.
  3531. if (read == (size_t)(-1)) {
  3532. mpack_tree_flag_error(tree, mpack_error_io);
  3533. return false;
  3534. }
  3535. // If the fill function returns 0, the data is not available yet. We
  3536. // return false to stop parsing the current node.
  3537. if (read == 0) {
  3538. mpack_log("not enough data.\n");
  3539. return false;
  3540. }
  3541. mpack_log("read %u more bytes\n", (uint32_t)read);
  3542. tree->data_length += read;
  3543. tree->parser.possible_nodes_left += read;
  3544. } while (tree->parser.possible_nodes_left < bytes);
  3545. return true;
  3546. }
  3547. #endif
  3548. /*
  3549. * Ensures there are enough additional bytes in the tree for the current node
  3550. * (including reserved bytes for the children of this node, and in addition to
  3551. * the reserved bytes for children of previous compound nodes), reading more
  3552. * data if needed.
  3553. *
  3554. * extra_bytes is the number of additional bytes to reserve for the current
  3555. * node beyond the type byte (since one byte is already reserved for each node
  3556. * by its parent array or map.)
  3557. *
  3558. * This may reallocate the tree, which means the tree->data pointer may change!
  3559. *
  3560. * Returns false if not enough bytes could be read.
  3561. */
  3562. MPACK_STATIC_INLINE bool mpack_tree_reserve_bytes(mpack_tree_t* tree, size_t extra_bytes) {
  3563. mpack_assert(tree->parser.state == mpack_tree_parse_state_in_progress);
  3564. // We guard against overflow here. A compound type could declare more than
  3565. // UINT32_MAX contents which overflows SIZE_MAX on 32-bit platforms. We
  3566. // flag mpack_error_invalid instead of mpack_error_too_big since it's far
  3567. // more likely that the message is corrupt than that the data is valid but
  3568. // not parseable on this architecture (see test_read_node_possible() in
  3569. // test-node.c .)
  3570. if ((uint64_t)tree->parser.current_node_reserved + (uint64_t)extra_bytes > SIZE_MAX) {
  3571. mpack_tree_flag_error(tree, mpack_error_invalid);
  3572. return false;
  3573. }
  3574. tree->parser.current_node_reserved += extra_bytes;
  3575. // Note that possible_nodes_left already accounts for reserved bytes for
  3576. // children of previous compound nodes. So even if there are hundreds of
  3577. // bytes left in the buffer, we might need to read anyway.
  3578. if (tree->parser.current_node_reserved <= tree->parser.possible_nodes_left)
  3579. return true;
  3580. #ifdef MPACK_MALLOC
  3581. return mpack_tree_reserve_fill(tree);
  3582. #else
  3583. return false;
  3584. #endif
  3585. }
  3586. MPACK_STATIC_INLINE size_t mpack_tree_parser_stack_capacity(mpack_tree_t* tree) {
  3587. #ifdef MPACK_MALLOC
  3588. return tree->parser.stack_capacity;
  3589. #else
  3590. return sizeof(tree->parser.stack) / sizeof(tree->parser.stack[0]);
  3591. #endif
  3592. }
  3593. static bool mpack_tree_push_stack(mpack_tree_t* tree, mpack_node_data_t* first_child, size_t total) {
  3594. mpack_tree_parser_t* parser = &tree->parser;
  3595. mpack_assert(parser->state == mpack_tree_parse_state_in_progress);
  3596. // No need to push empty containers
  3597. if (total == 0)
  3598. return true;
  3599. // Make sure we have enough room in the stack
  3600. if (parser->level + 1 == mpack_tree_parser_stack_capacity(tree)) {
  3601. #ifdef MPACK_MALLOC
  3602. size_t new_capacity = parser->stack_capacity * 2;
  3603. mpack_log("growing parse stack to capacity %i\n", (int)new_capacity);
  3604. // Replace the stack-allocated parsing stack
  3605. if (!parser->stack_owned) {
  3606. mpack_level_t* new_stack = (mpack_level_t*)MPACK_MALLOC(sizeof(mpack_level_t) * new_capacity);
  3607. if (!new_stack) {
  3608. mpack_tree_flag_error(tree, mpack_error_memory);
  3609. return false;
  3610. }
  3611. mpack_memcpy(new_stack, parser->stack, sizeof(mpack_level_t) * parser->stack_capacity);
  3612. parser->stack = new_stack;
  3613. parser->stack_owned = true;
  3614. // Realloc the allocated parsing stack
  3615. } else {
  3616. mpack_level_t* new_stack = (mpack_level_t*)mpack_realloc(parser->stack,
  3617. sizeof(mpack_level_t) * parser->stack_capacity, sizeof(mpack_level_t) * new_capacity);
  3618. if (!new_stack) {
  3619. mpack_tree_flag_error(tree, mpack_error_memory);
  3620. return false;
  3621. }
  3622. parser->stack = new_stack;
  3623. }
  3624. parser->stack_capacity = new_capacity;
  3625. #else
  3626. mpack_tree_flag_error(tree, mpack_error_too_big);
  3627. return false;
  3628. #endif
  3629. }
  3630. // Push the contents of this node onto the parsing stack
  3631. ++parser->level;
  3632. parser->stack[parser->level].child = first_child;
  3633. parser->stack[parser->level].left = total;
  3634. return true;
  3635. }
  3636. static bool mpack_tree_parse_children(mpack_tree_t* tree, mpack_node_data_t* node) {
  3637. mpack_tree_parser_t* parser = &tree->parser;
  3638. mpack_assert(parser->state == mpack_tree_parse_state_in_progress);
  3639. mpack_type_t type = node->type;
  3640. size_t total = node->len;
  3641. // Calculate total elements to read
  3642. if (type == mpack_type_map) {
  3643. if ((uint64_t)total * 2 > SIZE_MAX) {
  3644. mpack_tree_flag_error(tree, mpack_error_too_big);
  3645. return false;
  3646. }
  3647. total *= 2;
  3648. }
  3649. // Make sure we are under our total node limit (TODO can this overflow?)
  3650. tree->node_count += total;
  3651. if (tree->node_count > tree->max_nodes) {
  3652. mpack_tree_flag_error(tree, mpack_error_too_big);
  3653. return false;
  3654. }
  3655. // Each node is at least one byte. Count these bytes now to make
  3656. // sure there is enough data left.
  3657. if (!mpack_tree_reserve_bytes(tree, total))
  3658. return false;
  3659. // If there are enough nodes left in the current page, no need to grow
  3660. if (total <= parser->nodes_left) {
  3661. node->value.children = parser->nodes;
  3662. parser->nodes += total;
  3663. parser->nodes_left -= total;
  3664. } else {
  3665. #ifdef MPACK_MALLOC
  3666. // We can't grow if we're using a fixed pool (i.e. we didn't start with a page)
  3667. if (!tree->next) {
  3668. mpack_tree_flag_error(tree, mpack_error_too_big);
  3669. return false;
  3670. }
  3671. // Otherwise we need to grow, and the node's children need to be contiguous.
  3672. // This is a heuristic to decide whether we should waste the remaining space
  3673. // in the current page and start a new one, or give the children their
  3674. // own page. With a fraction of 1/8, this causes at most 12% additional
  3675. // waste. Note that reducing this too much causes less cache coherence and
  3676. // more malloc() overhead due to smaller allocations, so there's a tradeoff
  3677. // here. This heuristic could use some improvement, especially with custom
  3678. // page sizes.
  3679. mpack_tree_page_t* page;
  3680. if (total > MPACK_NODES_PER_PAGE || parser->nodes_left > MPACK_NODES_PER_PAGE / 8) {
  3681. // TODO: this should check for overflow
  3682. page = (mpack_tree_page_t*)MPACK_MALLOC(
  3683. sizeof(mpack_tree_page_t) + sizeof(mpack_node_data_t) * (total - 1));
  3684. if (page == NULL) {
  3685. mpack_tree_flag_error(tree, mpack_error_memory);
  3686. return false;
  3687. }
  3688. mpack_log("allocated seperate page %p for %i children, %i left in page of %i total\n",
  3689. page, (int)total, (int)parser->nodes_left, (int)MPACK_NODES_PER_PAGE);
  3690. node->value.children = page->nodes;
  3691. } else {
  3692. page = (mpack_tree_page_t*)MPACK_MALLOC(MPACK_PAGE_ALLOC_SIZE);
  3693. if (page == NULL) {
  3694. mpack_tree_flag_error(tree, mpack_error_memory);
  3695. return false;
  3696. }
  3697. mpack_log("allocated new page %p for %i children, wasting %i in page of %i total\n",
  3698. page, (int)total, (int)parser->nodes_left, (int)MPACK_NODES_PER_PAGE);
  3699. node->value.children = page->nodes;
  3700. parser->nodes = page->nodes + total;
  3701. parser->nodes_left = MPACK_NODES_PER_PAGE - total;
  3702. }
  3703. page->next = tree->next;
  3704. tree->next = page;
  3705. #else
  3706. // We can't grow if we don't have an allocator
  3707. mpack_tree_flag_error(tree, mpack_error_too_big);
  3708. return false;
  3709. #endif
  3710. }
  3711. return mpack_tree_push_stack(tree, node->value.children, total);
  3712. }
  3713. static bool mpack_tree_parse_bytes(mpack_tree_t* tree, mpack_node_data_t* node) {
  3714. node->value.offset = tree->size + tree->parser.current_node_reserved + 1;
  3715. return mpack_tree_reserve_bytes(tree, node->len);
  3716. }
  3717. #if MPACK_EXTENSIONS
  3718. static bool mpack_tree_parse_ext(mpack_tree_t* tree, mpack_node_data_t* node) {
  3719. // reserve space for exttype
  3720. tree->parser.current_node_reserved += sizeof(int8_t);
  3721. node->type = mpack_type_ext;
  3722. return mpack_tree_parse_bytes(tree, node);
  3723. }
  3724. #endif
  3725. static bool mpack_tree_parse_node_contents(mpack_tree_t* tree, mpack_node_data_t* node) {
  3726. mpack_assert(tree->parser.state == mpack_tree_parse_state_in_progress);
  3727. mpack_assert(node != NULL, "null node?");
  3728. // read the type. we've already accounted for this byte in
  3729. // possible_nodes_left, so we already know it is in bounds, and we don't
  3730. // need to reserve it for this node.
  3731. mpack_assert(tree->data_length > tree->size);
  3732. uint8_t type = mpack_load_u8(tree->data + tree->size);
  3733. mpack_log("node type %x\n", type);
  3734. tree->parser.current_node_reserved = 0;
  3735. // as with mpack_read_tag(), the fastest way to parse a node is to switch
  3736. // on the first byte, and to explicitly list every possible byte. we switch
  3737. // on the first four bits in size-optimized builds.
  3738. #if MPACK_OPTIMIZE_FOR_SIZE
  3739. switch (type >> 4) {
  3740. // positive fixnum
  3741. case 0x0: case 0x1: case 0x2: case 0x3:
  3742. case 0x4: case 0x5: case 0x6: case 0x7:
  3743. node->type = mpack_type_uint;
  3744. node->value.u = type;
  3745. return true;
  3746. // negative fixnum
  3747. case 0xe: case 0xf:
  3748. node->type = mpack_type_int;
  3749. node->value.i = (int8_t)type;
  3750. return true;
  3751. // fixmap
  3752. case 0x8:
  3753. node->type = mpack_type_map;
  3754. node->len = (uint32_t)(type & ~0xf0);
  3755. return mpack_tree_parse_children(tree, node);
  3756. // fixarray
  3757. case 0x9:
  3758. node->type = mpack_type_array;
  3759. node->len = (uint32_t)(type & ~0xf0);
  3760. return mpack_tree_parse_children(tree, node);
  3761. // fixstr
  3762. case 0xa: case 0xb:
  3763. node->type = mpack_type_str;
  3764. node->len = (uint32_t)(type & ~0xe0);
  3765. return mpack_tree_parse_bytes(tree, node);
  3766. // not one of the common infix types
  3767. default:
  3768. break;
  3769. }
  3770. #endif
  3771. switch (type) {
  3772. #if !MPACK_OPTIMIZE_FOR_SIZE
  3773. // positive fixnum
  3774. case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
  3775. case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
  3776. case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
  3777. case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
  3778. case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
  3779. case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
  3780. case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
  3781. case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
  3782. case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
  3783. case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
  3784. case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
  3785. case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
  3786. case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
  3787. case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
  3788. case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
  3789. case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
  3790. node->type = mpack_type_uint;
  3791. node->value.u = type;
  3792. return true;
  3793. // negative fixnum
  3794. case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
  3795. case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
  3796. case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
  3797. case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
  3798. node->type = mpack_type_int;
  3799. node->value.i = (int8_t)type;
  3800. return true;
  3801. // fixmap
  3802. case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
  3803. case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
  3804. node->type = mpack_type_map;
  3805. node->len = (uint32_t)(type & ~0xf0);
  3806. return mpack_tree_parse_children(tree, node);
  3807. // fixarray
  3808. case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
  3809. case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
  3810. node->type = mpack_type_array;
  3811. node->len = (uint32_t)(type & ~0xf0);
  3812. return mpack_tree_parse_children(tree, node);
  3813. // fixstr
  3814. case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
  3815. case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
  3816. case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
  3817. case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
  3818. node->type = mpack_type_str;
  3819. node->len = (uint32_t)(type & ~0xe0);
  3820. return mpack_tree_parse_bytes(tree, node);
  3821. #endif
  3822. // nil
  3823. case 0xc0:
  3824. node->type = mpack_type_nil;
  3825. return true;
  3826. // bool
  3827. case 0xc2: case 0xc3:
  3828. node->type = mpack_type_bool;
  3829. node->value.b = type & 1;
  3830. return true;
  3831. // bin8
  3832. case 0xc4:
  3833. node->type = mpack_type_bin;
  3834. if (!mpack_tree_reserve_bytes(tree, sizeof(uint8_t)))
  3835. return false;
  3836. node->len = mpack_load_u8(tree->data + tree->size + 1);
  3837. return mpack_tree_parse_bytes(tree, node);
  3838. // bin16
  3839. case 0xc5:
  3840. node->type = mpack_type_bin;
  3841. if (!mpack_tree_reserve_bytes(tree, sizeof(uint16_t)))
  3842. return false;
  3843. node->len = mpack_load_u16(tree->data + tree->size + 1);
  3844. return mpack_tree_parse_bytes(tree, node);
  3845. // bin32
  3846. case 0xc6:
  3847. node->type = mpack_type_bin;
  3848. if (!mpack_tree_reserve_bytes(tree, sizeof(uint32_t)))
  3849. return false;
  3850. node->len = mpack_load_u32(tree->data + tree->size + 1);
  3851. return mpack_tree_parse_bytes(tree, node);
  3852. #if MPACK_EXTENSIONS
  3853. // ext8
  3854. case 0xc7:
  3855. if (!mpack_tree_reserve_bytes(tree, sizeof(uint8_t)))
  3856. return false;
  3857. node->len = mpack_load_u8(tree->data + tree->size + 1);
  3858. return mpack_tree_parse_ext(tree, node);
  3859. // ext16
  3860. case 0xc8:
  3861. if (!mpack_tree_reserve_bytes(tree, sizeof(uint16_t)))
  3862. return false;
  3863. node->len = mpack_load_u16(tree->data + tree->size + 1);
  3864. return mpack_tree_parse_ext(tree, node);
  3865. // ext32
  3866. case 0xc9:
  3867. if (!mpack_tree_reserve_bytes(tree, sizeof(uint32_t)))
  3868. return false;
  3869. node->len = mpack_load_u32(tree->data + tree->size + 1);
  3870. return mpack_tree_parse_ext(tree, node);
  3871. #endif
  3872. // float
  3873. case 0xca:
  3874. if (!mpack_tree_reserve_bytes(tree, sizeof(float)))
  3875. return false;
  3876. node->value.f = mpack_load_float(tree->data + tree->size + 1);
  3877. node->type = mpack_type_float;
  3878. return true;
  3879. // double
  3880. case 0xcb:
  3881. if (!mpack_tree_reserve_bytes(tree, sizeof(double)))
  3882. return false;
  3883. node->value.d = mpack_load_double(tree->data + tree->size + 1);
  3884. node->type = mpack_type_double;
  3885. return true;
  3886. // uint8
  3887. case 0xcc:
  3888. node->type = mpack_type_uint;
  3889. if (!mpack_tree_reserve_bytes(tree, sizeof(uint8_t)))
  3890. return false;
  3891. node->value.u = mpack_load_u8(tree->data + tree->size + 1);
  3892. return true;
  3893. // uint16
  3894. case 0xcd:
  3895. node->type = mpack_type_uint;
  3896. if (!mpack_tree_reserve_bytes(tree, sizeof(uint16_t)))
  3897. return false;
  3898. node->value.u = mpack_load_u16(tree->data + tree->size + 1);
  3899. return true;
  3900. // uint32
  3901. case 0xce:
  3902. node->type = mpack_type_uint;
  3903. if (!mpack_tree_reserve_bytes(tree, sizeof(uint32_t)))
  3904. return false;
  3905. node->value.u = mpack_load_u32(tree->data + tree->size + 1);
  3906. return true;
  3907. // uint64
  3908. case 0xcf:
  3909. node->type = mpack_type_uint;
  3910. if (!mpack_tree_reserve_bytes(tree, sizeof(uint64_t)))
  3911. return false;
  3912. node->value.u = mpack_load_u64(tree->data + tree->size + 1);
  3913. return true;
  3914. // int8
  3915. case 0xd0:
  3916. node->type = mpack_type_int;
  3917. if (!mpack_tree_reserve_bytes(tree, sizeof(int8_t)))
  3918. return false;
  3919. node->value.i = mpack_load_i8(tree->data + tree->size + 1);
  3920. return true;
  3921. // int16
  3922. case 0xd1:
  3923. node->type = mpack_type_int;
  3924. if (!mpack_tree_reserve_bytes(tree, sizeof(int16_t)))
  3925. return false;
  3926. node->value.i = mpack_load_i16(tree->data + tree->size + 1);
  3927. return true;
  3928. // int32
  3929. case 0xd2:
  3930. node->type = mpack_type_int;
  3931. if (!mpack_tree_reserve_bytes(tree, sizeof(int32_t)))
  3932. return false;
  3933. node->value.i = mpack_load_i32(tree->data + tree->size + 1);
  3934. return true;
  3935. // int64
  3936. case 0xd3:
  3937. node->type = mpack_type_int;
  3938. if (!mpack_tree_reserve_bytes(tree, sizeof(int64_t)))
  3939. return false;
  3940. node->value.i = mpack_load_i64(tree->data + tree->size + 1);
  3941. return true;
  3942. #if MPACK_EXTENSIONS
  3943. // fixext1
  3944. case 0xd4:
  3945. node->len = 1;
  3946. return mpack_tree_parse_ext(tree, node);
  3947. // fixext2
  3948. case 0xd5:
  3949. node->len = 2;
  3950. return mpack_tree_parse_ext(tree, node);
  3951. // fixext4
  3952. case 0xd6:
  3953. node->len = 4;
  3954. return mpack_tree_parse_ext(tree, node);
  3955. // fixext8
  3956. case 0xd7:
  3957. node->len = 8;
  3958. return mpack_tree_parse_ext(tree, node);
  3959. // fixext16
  3960. case 0xd8:
  3961. node->len = 16;
  3962. return mpack_tree_parse_ext(tree, node);
  3963. #endif
  3964. // str8
  3965. case 0xd9:
  3966. if (!mpack_tree_reserve_bytes(tree, sizeof(uint8_t)))
  3967. return false;
  3968. node->len = mpack_load_u8(tree->data + tree->size + 1);
  3969. node->type = mpack_type_str;
  3970. return mpack_tree_parse_bytes(tree, node);
  3971. // str16
  3972. case 0xda:
  3973. if (!mpack_tree_reserve_bytes(tree, sizeof(uint16_t)))
  3974. return false;
  3975. node->len = mpack_load_u16(tree->data + tree->size + 1);
  3976. node->type = mpack_type_str;
  3977. return mpack_tree_parse_bytes(tree, node);
  3978. // str32
  3979. case 0xdb:
  3980. if (!mpack_tree_reserve_bytes(tree, sizeof(uint32_t)))
  3981. return false;
  3982. node->len = mpack_load_u32(tree->data + tree->size + 1);
  3983. node->type = mpack_type_str;
  3984. return mpack_tree_parse_bytes(tree, node);
  3985. // array16
  3986. case 0xdc:
  3987. if (!mpack_tree_reserve_bytes(tree, sizeof(uint16_t)))
  3988. return false;
  3989. node->len = mpack_load_u16(tree->data + tree->size + 1);
  3990. node->type = mpack_type_array;
  3991. return mpack_tree_parse_children(tree, node);
  3992. // array32
  3993. case 0xdd:
  3994. if (!mpack_tree_reserve_bytes(tree, sizeof(uint32_t)))
  3995. return false;
  3996. node->len = mpack_load_u32(tree->data + tree->size + 1);
  3997. node->type = mpack_type_array;
  3998. return mpack_tree_parse_children(tree, node);
  3999. // map16
  4000. case 0xde:
  4001. if (!mpack_tree_reserve_bytes(tree, sizeof(uint16_t)))
  4002. return false;
  4003. node->len = mpack_load_u16(tree->data + tree->size + 1);
  4004. node->type = mpack_type_map;
  4005. return mpack_tree_parse_children(tree, node);
  4006. // map32
  4007. case 0xdf:
  4008. if (!mpack_tree_reserve_bytes(tree, sizeof(uint32_t)))
  4009. return false;
  4010. node->len = mpack_load_u32(tree->data + tree->size + 1);
  4011. node->type = mpack_type_map;
  4012. return mpack_tree_parse_children(tree, node);
  4013. // reserved
  4014. case 0xc1:
  4015. mpack_tree_flag_error(tree, mpack_error_invalid);
  4016. return false;
  4017. #if !MPACK_EXTENSIONS
  4018. // ext
  4019. case 0xc7: // fallthrough
  4020. case 0xc8: // fallthrough
  4021. case 0xc9: // fallthrough
  4022. // fixext
  4023. case 0xd4: // fallthrough
  4024. case 0xd5: // fallthrough
  4025. case 0xd6: // fallthrough
  4026. case 0xd7: // fallthrough
  4027. case 0xd8:
  4028. mpack_tree_flag_error(tree, mpack_error_unsupported);
  4029. return false;
  4030. #endif
  4031. #if MPACK_OPTIMIZE_FOR_SIZE
  4032. // any other bytes should have been handled by the infix switch
  4033. default:
  4034. break;
  4035. #endif
  4036. }
  4037. mpack_assert(0, "unreachable");
  4038. return false;
  4039. }
  4040. static bool mpack_tree_parse_node(mpack_tree_t* tree, mpack_node_data_t* node) {
  4041. mpack_log("parsing a node at position %i in level %i\n",
  4042. (int)tree->size, (int)tree->parser.level);
  4043. if (!mpack_tree_parse_node_contents(tree, node)) {
  4044. mpack_log("node parsing returned false\n");
  4045. return false;
  4046. }
  4047. tree->parser.possible_nodes_left -= tree->parser.current_node_reserved;
  4048. // The reserve for the current node does not include the initial byte
  4049. // previously reserved as part of its parent.
  4050. size_t node_size = tree->parser.current_node_reserved + 1;
  4051. // If the parsed type is a map or array, the reserve includes one byte for
  4052. // each child. We want to subtract these out of possible_nodes_left, but
  4053. // not out of the current size of the tree.
  4054. if (node->type == mpack_type_array)
  4055. node_size -= node->len;
  4056. else if (node->type == mpack_type_map)
  4057. node_size -= node->len * 2;
  4058. tree->size += node_size;
  4059. mpack_log("parsed a node of type %s of %i bytes and "
  4060. "%i additional bytes reserved for children.\n",
  4061. mpack_type_to_string(node->type), (int)node_size,
  4062. (int)tree->parser.current_node_reserved + 1 - (int)node_size);
  4063. return true;
  4064. }
  4065. /*
  4066. * We read nodes in a loop instead of recursively for maximum performance. The
  4067. * stack holds the amount of children left to read in each level of the tree.
  4068. * Parsing can pause and resume when more data becomes available.
  4069. */
  4070. static bool mpack_tree_continue_parsing(mpack_tree_t* tree) {
  4071. if (mpack_tree_error(tree) != mpack_ok)
  4072. return false;
  4073. mpack_tree_parser_t* parser = &tree->parser;
  4074. mpack_assert(parser->state == mpack_tree_parse_state_in_progress);
  4075. mpack_log("parsing tree elements, %i bytes in buffer\n", (int)tree->data_length);
  4076. // we loop parsing nodes until the parse stack is empty. we break
  4077. // by returning out of the function.
  4078. while (true) {
  4079. mpack_node_data_t* node = parser->stack[parser->level].child;
  4080. size_t level = parser->level;
  4081. if (!mpack_tree_parse_node(tree, node))
  4082. return false;
  4083. --parser->stack[level].left;
  4084. ++parser->stack[level].child;
  4085. mpack_assert(mpack_tree_error(tree) == mpack_ok,
  4086. "mpack_tree_parse_node() should have returned false due to error!");
  4087. // pop empty stack levels, exiting the outer loop when the stack is empty.
  4088. // (we could tail-optimize containers by pre-emptively popping empty
  4089. // stack levels before reading the new element, this way we wouldn't
  4090. // have to loop. but we eventually want to use the parse stack to give
  4091. // better error messages that contain the location of the error, so
  4092. // it needs to be complete.)
  4093. while (parser->stack[parser->level].left == 0) {
  4094. if (parser->level == 0)
  4095. return true;
  4096. --parser->level;
  4097. }
  4098. }
  4099. }
  4100. static void mpack_tree_cleanup(mpack_tree_t* tree) {
  4101. MPACK_UNUSED(tree);
  4102. #ifdef MPACK_MALLOC
  4103. if (tree->parser.stack_owned) {
  4104. MPACK_FREE(tree->parser.stack);
  4105. tree->parser.stack = NULL;
  4106. tree->parser.stack_owned = false;
  4107. }
  4108. mpack_tree_page_t* page = tree->next;
  4109. while (page != NULL) {
  4110. mpack_tree_page_t* next = page->next;
  4111. mpack_log("freeing page %p\n", page);
  4112. MPACK_FREE(page);
  4113. page = next;
  4114. }
  4115. tree->next = NULL;
  4116. #endif
  4117. }
  4118. static bool mpack_tree_parse_start(mpack_tree_t* tree) {
  4119. if (mpack_tree_error(tree) != mpack_ok)
  4120. return false;
  4121. mpack_tree_parser_t* parser = &tree->parser;
  4122. mpack_assert(parser->state != mpack_tree_parse_state_in_progress,
  4123. "previous parsing was not finished!");
  4124. if (parser->state == mpack_tree_parse_state_parsed)
  4125. mpack_tree_cleanup(tree);
  4126. mpack_log("starting parse\n");
  4127. tree->parser.state = mpack_tree_parse_state_in_progress;
  4128. tree->parser.current_node_reserved = 0;
  4129. // check if we previously parsed a tree
  4130. if (tree->size > 0) {
  4131. #ifdef MPACK_MALLOC
  4132. // if we're buffered, move the remaining data back to the
  4133. // start of the buffer
  4134. // TODO: This is not ideal performance-wise. We should only move data
  4135. // when we need to call the fill function.
  4136. // TODO: We could consider shrinking the buffer here, especially if we
  4137. // determine that the fill function is providing less than a quarter of
  4138. // the buffer size or if messages take up less than a quarter of the
  4139. // buffer size. Maybe this should be configurable.
  4140. if (tree->buffer != NULL) {
  4141. mpack_memmove(tree->buffer, tree->buffer + tree->size, tree->data_length - tree->size);
  4142. }
  4143. else
  4144. #endif
  4145. // otherwise advance past the parsed data
  4146. {
  4147. tree->data += tree->size;
  4148. }
  4149. tree->data_length -= tree->size;
  4150. tree->size = 0;
  4151. tree->node_count = 0;
  4152. }
  4153. // make sure we have at least one byte available before allocating anything
  4154. parser->possible_nodes_left = tree->data_length;
  4155. if (!mpack_tree_reserve_bytes(tree, sizeof(uint8_t))) {
  4156. tree->parser.state = mpack_tree_parse_state_not_started;
  4157. return false;
  4158. }
  4159. mpack_log("parsing tree at %p starting with byte %x\n", tree->data, (uint8_t)tree->data[0]);
  4160. parser->possible_nodes_left -= 1;
  4161. tree->node_count = 1;
  4162. #ifdef MPACK_MALLOC
  4163. parser->stack = parser->stack_local;
  4164. parser->stack_owned = false;
  4165. parser->stack_capacity = sizeof(parser->stack_local) / sizeof(*parser->stack_local);
  4166. if (tree->pool == NULL) {
  4167. // allocate first page
  4168. mpack_tree_page_t* page = (mpack_tree_page_t*)MPACK_MALLOC(MPACK_PAGE_ALLOC_SIZE);
  4169. mpack_log("allocated initial page %p of size %i count %i\n",
  4170. page, (int)MPACK_PAGE_ALLOC_SIZE, (int)MPACK_NODES_PER_PAGE);
  4171. if (page == NULL) {
  4172. tree->error = mpack_error_memory;
  4173. return false;
  4174. }
  4175. page->next = NULL;
  4176. tree->next = page;
  4177. parser->nodes = page->nodes;
  4178. parser->nodes_left = MPACK_NODES_PER_PAGE;
  4179. }
  4180. else
  4181. #endif
  4182. {
  4183. // otherwise use the provided pool
  4184. mpack_assert(tree->pool != NULL, "no pool provided?");
  4185. parser->nodes = tree->pool;
  4186. parser->nodes_left = tree->pool_count;
  4187. }
  4188. tree->root = parser->nodes;
  4189. ++parser->nodes;
  4190. --parser->nodes_left;
  4191. parser->level = 0;
  4192. parser->stack[0].child = tree->root;
  4193. parser->stack[0].left = 1;
  4194. return true;
  4195. }
  4196. void mpack_tree_parse(mpack_tree_t* tree) {
  4197. if (mpack_tree_error(tree) != mpack_ok)
  4198. return;
  4199. if (tree->parser.state != mpack_tree_parse_state_in_progress) {
  4200. if (!mpack_tree_parse_start(tree)) {
  4201. mpack_tree_flag_error(tree, (tree->read_fn == NULL) ?
  4202. mpack_error_invalid : mpack_error_io);
  4203. return;
  4204. }
  4205. }
  4206. if (!mpack_tree_continue_parsing(tree)) {
  4207. if (mpack_tree_error(tree) != mpack_ok)
  4208. return;
  4209. // We're parsing synchronously on a blocking fill function. If we
  4210. // didn't completely finish parsing the tree, it's an error.
  4211. mpack_log("tree parsing incomplete. flagging error.\n");
  4212. mpack_tree_flag_error(tree, (tree->read_fn == NULL) ?
  4213. mpack_error_invalid : mpack_error_io);
  4214. return;
  4215. }
  4216. mpack_assert(mpack_tree_error(tree) == mpack_ok);
  4217. mpack_assert(tree->parser.level == 0);
  4218. tree->parser.state = mpack_tree_parse_state_parsed;
  4219. mpack_log("parsed tree of %i bytes, %i bytes left\n", (int)tree->size, (int)tree->parser.possible_nodes_left);
  4220. mpack_log("%i nodes in final page\n", (int)tree->parser.nodes_left);
  4221. }
  4222. bool mpack_tree_try_parse(mpack_tree_t* tree) {
  4223. if (mpack_tree_error(tree) != mpack_ok)
  4224. return false;
  4225. if (tree->parser.state != mpack_tree_parse_state_in_progress)
  4226. if (!mpack_tree_parse_start(tree))
  4227. return false;
  4228. if (!mpack_tree_continue_parsing(tree))
  4229. return false;
  4230. mpack_assert(mpack_tree_error(tree) == mpack_ok);
  4231. mpack_assert(tree->parser.level == 0);
  4232. tree->parser.state = mpack_tree_parse_state_parsed;
  4233. return true;
  4234. }
  4235. /*
  4236. * Tree functions
  4237. */
  4238. mpack_node_t mpack_tree_root(mpack_tree_t* tree) {
  4239. if (mpack_tree_error(tree) != mpack_ok)
  4240. return mpack_tree_nil_node(tree);
  4241. // We check that a tree was parsed successfully and assert if not. You must
  4242. // call mpack_tree_parse() (or mpack_tree_try_parse() with a success
  4243. // result) in order to access the root node.
  4244. if (tree->parser.state != mpack_tree_parse_state_parsed) {
  4245. mpack_break("Tree has not been parsed! "
  4246. "Did you call mpack_tree_parse() or mpack_tree_try_parse()?");
  4247. mpack_tree_flag_error(tree, mpack_error_bug);
  4248. return mpack_tree_nil_node(tree);
  4249. }
  4250. return mpack_node(tree, tree->root);
  4251. }
  4252. static void mpack_tree_init_clear(mpack_tree_t* tree) {
  4253. mpack_memset(tree, 0, sizeof(*tree));
  4254. tree->nil_node.type = mpack_type_nil;
  4255. tree->missing_node.type = mpack_type_missing;
  4256. tree->max_size = SIZE_MAX;
  4257. tree->max_nodes = SIZE_MAX;
  4258. }
  4259. #ifdef MPACK_MALLOC
  4260. void mpack_tree_init_data(mpack_tree_t* tree, const char* data, size_t length) {
  4261. mpack_tree_init_clear(tree);
  4262. MPACK_STATIC_ASSERT(MPACK_NODE_PAGE_SIZE >= sizeof(mpack_tree_page_t),
  4263. "MPACK_NODE_PAGE_SIZE is too small");
  4264. MPACK_STATIC_ASSERT(MPACK_PAGE_ALLOC_SIZE <= MPACK_NODE_PAGE_SIZE,
  4265. "incorrect page rounding?");
  4266. tree->data = data;
  4267. tree->data_length = length;
  4268. tree->pool = NULL;
  4269. tree->pool_count = 0;
  4270. tree->next = NULL;
  4271. mpack_log("===========================\n");
  4272. mpack_log("initializing tree with data of size %i\n", (int)length);
  4273. }
  4274. #endif
  4275. void mpack_tree_init_pool(mpack_tree_t* tree, const char* data, size_t length,
  4276. mpack_node_data_t* node_pool, size_t node_pool_count)
  4277. {
  4278. mpack_tree_init_clear(tree);
  4279. #ifdef MPACK_MALLOC
  4280. tree->next = NULL;
  4281. #endif
  4282. if (node_pool_count == 0) {
  4283. mpack_break("initial page has no nodes!");
  4284. mpack_tree_flag_error(tree, mpack_error_bug);
  4285. return;
  4286. }
  4287. tree->data = data;
  4288. tree->data_length = length;
  4289. tree->pool = node_pool;
  4290. tree->pool_count = node_pool_count;
  4291. mpack_log("===========================\n");
  4292. mpack_log("initializing tree with data of size %i and pool of count %i\n",
  4293. (int)length, (int)node_pool_count);
  4294. }
  4295. void mpack_tree_init_error(mpack_tree_t* tree, mpack_error_t error) {
  4296. mpack_tree_init_clear(tree);
  4297. tree->error = error;
  4298. mpack_log("===========================\n");
  4299. mpack_log("initializing tree error state %i\n", (int)error);
  4300. }
  4301. #ifdef MPACK_MALLOC
  4302. void mpack_tree_init_stream(mpack_tree_t* tree, mpack_tree_read_t read_fn, void* context,
  4303. size_t max_message_size, size_t max_message_nodes) {
  4304. mpack_tree_init_clear(tree);
  4305. tree->read_fn = read_fn;
  4306. tree->context = context;
  4307. mpack_tree_set_limits(tree, max_message_size, max_message_nodes);
  4308. tree->max_size = max_message_size;
  4309. tree->max_nodes = max_message_nodes;
  4310. mpack_log("===========================\n");
  4311. mpack_log("initializing tree with stream, max size %i max nodes %i\n",
  4312. (int)max_message_size, (int)max_message_nodes);
  4313. }
  4314. #endif
  4315. void mpack_tree_set_limits(mpack_tree_t* tree, size_t max_message_size, size_t max_message_nodes) {
  4316. mpack_assert(max_message_size > 0);
  4317. mpack_assert(max_message_nodes > 0);
  4318. tree->max_size = max_message_size;
  4319. tree->max_nodes = max_message_nodes;
  4320. }
  4321. #if MPACK_STDIO
  4322. typedef struct mpack_file_tree_t {
  4323. char* data;
  4324. size_t size;
  4325. char buffer[MPACK_BUFFER_SIZE];
  4326. } mpack_file_tree_t;
  4327. static void mpack_file_tree_teardown(mpack_tree_t* tree) {
  4328. mpack_file_tree_t* file_tree = (mpack_file_tree_t*)tree->context;
  4329. MPACK_FREE(file_tree->data);
  4330. MPACK_FREE(file_tree);
  4331. }
  4332. static bool mpack_file_tree_read(mpack_tree_t* tree, mpack_file_tree_t* file_tree, FILE* file, size_t max_bytes) {
  4333. // get the file size
  4334. errno = 0;
  4335. int error = 0;
  4336. fseek(file, 0, SEEK_END);
  4337. error |= errno;
  4338. long size = ftell(file);
  4339. error |= errno;
  4340. fseek(file, 0, SEEK_SET);
  4341. error |= errno;
  4342. // check for errors
  4343. if (error != 0 || size < 0) {
  4344. mpack_tree_init_error(tree, mpack_error_io);
  4345. return false;
  4346. }
  4347. if (size == 0) {
  4348. mpack_tree_init_error(tree, mpack_error_invalid);
  4349. return false;
  4350. }
  4351. // make sure the size is less than max_bytes
  4352. // (this mess exists to safely convert between long and size_t regardless of their widths)
  4353. if (max_bytes != 0 && (((uint64_t)LONG_MAX > (uint64_t)SIZE_MAX && size > (long)SIZE_MAX) || (size_t)size > max_bytes)) {
  4354. mpack_tree_init_error(tree, mpack_error_too_big);
  4355. return false;
  4356. }
  4357. // allocate data
  4358. file_tree->data = (char*)MPACK_MALLOC((size_t)size);
  4359. if (file_tree->data == NULL) {
  4360. mpack_tree_init_error(tree, mpack_error_memory);
  4361. return false;
  4362. }
  4363. // read the file
  4364. long total = 0;
  4365. while (total < size) {
  4366. size_t read = fread(file_tree->data + total, 1, (size_t)(size - total), file);
  4367. if (read <= 0) {
  4368. mpack_tree_init_error(tree, mpack_error_io);
  4369. MPACK_FREE(file_tree->data);
  4370. return false;
  4371. }
  4372. total += (long)read;
  4373. }
  4374. file_tree->size = (size_t)size;
  4375. return true;
  4376. }
  4377. static bool mpack_tree_file_check_max_bytes(mpack_tree_t* tree, size_t max_bytes) {
  4378. // the C STDIO family of file functions use long (e.g. ftell)
  4379. if (max_bytes > LONG_MAX) {
  4380. mpack_break("max_bytes of %" PRIu64 " is invalid, maximum is LONG_MAX", (uint64_t)max_bytes);
  4381. mpack_tree_init_error(tree, mpack_error_bug);
  4382. return false;
  4383. }
  4384. return true;
  4385. }
  4386. static void mpack_tree_init_stdfile_noclose(mpack_tree_t* tree, FILE* stdfile, size_t max_bytes) {
  4387. // allocate file tree
  4388. mpack_file_tree_t* file_tree = (mpack_file_tree_t*) MPACK_MALLOC(sizeof(mpack_file_tree_t));
  4389. if (file_tree == NULL) {
  4390. mpack_tree_init_error(tree, mpack_error_memory);
  4391. return;
  4392. }
  4393. // read all data
  4394. if (!mpack_file_tree_read(tree, file_tree, stdfile, max_bytes)) {
  4395. MPACK_FREE(file_tree);
  4396. return;
  4397. }
  4398. mpack_tree_init_data(tree, file_tree->data, file_tree->size);
  4399. mpack_tree_set_context(tree, file_tree);
  4400. mpack_tree_set_teardown(tree, mpack_file_tree_teardown);
  4401. }
  4402. void mpack_tree_init_stdfile(mpack_tree_t* tree, FILE* stdfile, size_t max_bytes, bool close_when_done) {
  4403. if (!mpack_tree_file_check_max_bytes(tree, max_bytes))
  4404. return;
  4405. mpack_tree_init_stdfile_noclose(tree, stdfile, max_bytes);
  4406. if (close_when_done)
  4407. fclose(stdfile);
  4408. }
  4409. void mpack_tree_init_filename(mpack_tree_t* tree, const char* filename, size_t max_bytes) {
  4410. if (!mpack_tree_file_check_max_bytes(tree, max_bytes))
  4411. return;
  4412. // open the file
  4413. FILE* file = fopen(filename, "rb");
  4414. if (!file) {
  4415. mpack_tree_init_error(tree, mpack_error_io);
  4416. return;
  4417. }
  4418. mpack_tree_init_stdfile(tree, file, max_bytes, true);
  4419. }
  4420. #endif
  4421. mpack_error_t mpack_tree_destroy(mpack_tree_t* tree) {
  4422. mpack_tree_cleanup(tree);
  4423. #ifdef MPACK_MALLOC
  4424. if (tree->buffer)
  4425. MPACK_FREE(tree->buffer);
  4426. #endif
  4427. if (tree->teardown)
  4428. tree->teardown(tree);
  4429. tree->teardown = NULL;
  4430. return tree->error;
  4431. }
  4432. void mpack_tree_flag_error(mpack_tree_t* tree, mpack_error_t error) {
  4433. if (tree->error == mpack_ok) {
  4434. mpack_log("tree %p setting error %i: %s\n", tree, (int)error, mpack_error_to_string(error));
  4435. tree->error = error;
  4436. if (tree->error_fn)
  4437. tree->error_fn(tree, error);
  4438. }
  4439. }
  4440. /*
  4441. * Node misc functions
  4442. */
  4443. void mpack_node_flag_error(mpack_node_t node, mpack_error_t error) {
  4444. mpack_tree_flag_error(node.tree, error);
  4445. }
  4446. mpack_tag_t mpack_node_tag(mpack_node_t node) {
  4447. if (mpack_node_error(node) != mpack_ok)
  4448. return mpack_tag_nil();
  4449. mpack_tag_t tag = MPACK_TAG_ZERO;
  4450. tag.type = node.data->type;
  4451. switch (node.data->type) {
  4452. case mpack_type_missing:
  4453. // If a node is missing, I don't know if it makes sense to ask for
  4454. // a tag for it. We'll return a missing tag to match the missing
  4455. // node I guess, but attempting to use the tag for anything (like
  4456. // writing it for example) will flag mpack_error_bug.
  4457. break;
  4458. case mpack_type_nil: break;
  4459. case mpack_type_bool: tag.v.b = node.data->value.b; break;
  4460. case mpack_type_float: tag.v.f = node.data->value.f; break;
  4461. case mpack_type_double: tag.v.d = node.data->value.d; break;
  4462. case mpack_type_int: tag.v.i = node.data->value.i; break;
  4463. case mpack_type_uint: tag.v.u = node.data->value.u; break;
  4464. case mpack_type_str: tag.v.l = node.data->len; break;
  4465. case mpack_type_bin: tag.v.l = node.data->len; break;
  4466. #if MPACK_EXTENSIONS
  4467. case mpack_type_ext:
  4468. tag.v.l = node.data->len;
  4469. tag.exttype = mpack_node_exttype_unchecked(node);
  4470. break;
  4471. #endif
  4472. case mpack_type_array: tag.v.n = node.data->len; break;
  4473. case mpack_type_map: tag.v.n = node.data->len; break;
  4474. default:
  4475. mpack_assert(0, "unrecognized type %i", (int)node.data->type);
  4476. break;
  4477. }
  4478. return tag;
  4479. }
  4480. #if MPACK_DEBUG && MPACK_STDIO
  4481. static void mpack_node_print_element(mpack_node_t node, mpack_print_t* print, size_t depth) {
  4482. mpack_node_data_t* data = node.data;
  4483. switch (data->type) {
  4484. case mpack_type_str:
  4485. {
  4486. mpack_print_append_cstr(print, "\"");
  4487. const char* bytes = mpack_node_data_unchecked(node);
  4488. for (size_t i = 0; i < data->len; ++i) {
  4489. char c = bytes[i];
  4490. switch (c) {
  4491. case '\n': mpack_print_append_cstr(print, "\\n"); break;
  4492. case '\\': mpack_print_append_cstr(print, "\\\\"); break;
  4493. case '"': mpack_print_append_cstr(print, "\\\""); break;
  4494. default: mpack_print_append(print, &c, 1); break;
  4495. }
  4496. }
  4497. mpack_print_append_cstr(print, "\"");
  4498. }
  4499. break;
  4500. case mpack_type_array:
  4501. mpack_print_append_cstr(print, "[\n");
  4502. for (size_t i = 0; i < data->len; ++i) {
  4503. for (size_t j = 0; j < depth + 1; ++j)
  4504. mpack_print_append_cstr(print, " ");
  4505. mpack_node_print_element(mpack_node_array_at(node, i), print, depth + 1);
  4506. if (i != data->len - 1)
  4507. mpack_print_append_cstr(print, ",");
  4508. mpack_print_append_cstr(print, "\n");
  4509. }
  4510. for (size_t i = 0; i < depth; ++i)
  4511. mpack_print_append_cstr(print, " ");
  4512. mpack_print_append_cstr(print, "]");
  4513. break;
  4514. case mpack_type_map:
  4515. mpack_print_append_cstr(print, "{\n");
  4516. for (size_t i = 0; i < data->len; ++i) {
  4517. for (size_t j = 0; j < depth + 1; ++j)
  4518. mpack_print_append_cstr(print, " ");
  4519. mpack_node_print_element(mpack_node_map_key_at(node, i), print, depth + 1);
  4520. mpack_print_append_cstr(print, ": ");
  4521. mpack_node_print_element(mpack_node_map_value_at(node, i), print, depth + 1);
  4522. if (i != data->len - 1)
  4523. mpack_print_append_cstr(print, ",");
  4524. mpack_print_append_cstr(print, "\n");
  4525. }
  4526. for (size_t i = 0; i < depth; ++i)
  4527. mpack_print_append_cstr(print, " ");
  4528. mpack_print_append_cstr(print, "}");
  4529. break;
  4530. default:
  4531. {
  4532. const char* prefix = NULL;
  4533. size_t prefix_length = 0;
  4534. if (mpack_node_type(node) == mpack_type_bin
  4535. #if MPACK_EXTENSIONS
  4536. || mpack_node_type(node) == mpack_type_ext
  4537. #endif
  4538. ) {
  4539. prefix = mpack_node_data(node);
  4540. prefix_length = mpack_node_data_len(node);
  4541. }
  4542. char buf[256];
  4543. mpack_tag_t tag = mpack_node_tag(node);
  4544. mpack_tag_debug_pseudo_json(tag, buf, sizeof(buf), prefix, prefix_length);
  4545. mpack_print_append_cstr(print, buf);
  4546. }
  4547. break;
  4548. }
  4549. }
  4550. void mpack_node_print_to_buffer(mpack_node_t node, char* buffer, size_t buffer_size) {
  4551. if (buffer_size == 0) {
  4552. mpack_assert(false, "buffer size is zero!");
  4553. return;
  4554. }
  4555. mpack_print_t print;
  4556. mpack_memset(&print, 0, sizeof(print));
  4557. print.buffer = buffer;
  4558. print.size = buffer_size;
  4559. mpack_node_print_element(node, &print, 0);
  4560. mpack_print_append(&print, "", 1); // null-terminator
  4561. mpack_print_flush(&print);
  4562. // we always make sure there's a null-terminator at the end of the buffer
  4563. // in case we ran out of space.
  4564. print.buffer[print.size - 1] = '\0';
  4565. }
  4566. void mpack_node_print_to_callback(mpack_node_t node, mpack_print_callback_t callback, void* context) {
  4567. char buffer[1024];
  4568. mpack_print_t print;
  4569. mpack_memset(&print, 0, sizeof(print));
  4570. print.buffer = buffer;
  4571. print.size = sizeof(buffer);
  4572. print.callback = callback;
  4573. print.context = context;
  4574. mpack_node_print_element(node, &print, 0);
  4575. mpack_print_flush(&print);
  4576. }
  4577. void mpack_node_print_to_file(mpack_node_t node, FILE* file) {
  4578. mpack_assert(file != NULL, "file is NULL");
  4579. char buffer[1024];
  4580. mpack_print_t print;
  4581. mpack_memset(&print, 0, sizeof(print));
  4582. print.buffer = buffer;
  4583. print.size = sizeof(buffer);
  4584. print.callback = &mpack_print_file_callback;
  4585. print.context = file;
  4586. size_t depth = 2;
  4587. for (size_t i = 0; i < depth; ++i)
  4588. mpack_print_append_cstr(&print, " ");
  4589. mpack_node_print_element(node, &print, depth);
  4590. mpack_print_append_cstr(&print, "\n");
  4591. mpack_print_flush(&print);
  4592. }
  4593. #endif
  4594. /*
  4595. * Node Value Functions
  4596. */
  4597. #if MPACK_EXTENSIONS
  4598. mpack_timestamp_t mpack_node_timestamp(mpack_node_t node) {
  4599. mpack_timestamp_t timestamp = {0, 0};
  4600. // we'll let mpack_node_exttype() do most checks
  4601. if (mpack_node_exttype(node) != MPACK_EXTTYPE_TIMESTAMP) {
  4602. mpack_log("exttype %i\n", mpack_node_exttype(node));
  4603. mpack_node_flag_error(node, mpack_error_type);
  4604. return timestamp;
  4605. }
  4606. const char* p = mpack_node_data_unchecked(node);
  4607. switch (node.data->len) {
  4608. case 4:
  4609. timestamp.nanoseconds = 0;
  4610. timestamp.seconds = mpack_load_u32(p);
  4611. break;
  4612. case 8: {
  4613. uint64_t value = mpack_load_u64(p);
  4614. timestamp.nanoseconds = (uint32_t)(value >> 34);
  4615. timestamp.seconds = value & ((UINT64_C(1) << 34) - 1);
  4616. break;
  4617. }
  4618. case 12:
  4619. timestamp.nanoseconds = mpack_load_u32(p);
  4620. timestamp.seconds = mpack_load_i64(p + 4);
  4621. break;
  4622. default:
  4623. mpack_tree_flag_error(node.tree, mpack_error_invalid);
  4624. return timestamp;
  4625. }
  4626. if (timestamp.nanoseconds > MPACK_TIMESTAMP_NANOSECONDS_MAX) {
  4627. mpack_tree_flag_error(node.tree, mpack_error_invalid);
  4628. mpack_timestamp_t zero = {0, 0};
  4629. return zero;
  4630. }
  4631. return timestamp;
  4632. }
  4633. int64_t mpack_node_timestamp_seconds(mpack_node_t node) {
  4634. return mpack_node_timestamp(node).seconds;
  4635. }
  4636. uint32_t mpack_node_timestamp_nanoseconds(mpack_node_t node) {
  4637. return mpack_node_timestamp(node).nanoseconds;
  4638. }
  4639. #endif
  4640. /*
  4641. * Node Data Functions
  4642. */
  4643. void mpack_node_check_utf8(mpack_node_t node) {
  4644. if (mpack_node_error(node) != mpack_ok)
  4645. return;
  4646. mpack_node_data_t* data = node.data;
  4647. if (data->type != mpack_type_str || !mpack_utf8_check(mpack_node_data_unchecked(node), data->len))
  4648. mpack_node_flag_error(node, mpack_error_type);
  4649. }
  4650. void mpack_node_check_utf8_cstr(mpack_node_t node) {
  4651. if (mpack_node_error(node) != mpack_ok)
  4652. return;
  4653. mpack_node_data_t* data = node.data;
  4654. if (data->type != mpack_type_str || !mpack_utf8_check_no_null(mpack_node_data_unchecked(node), data->len))
  4655. mpack_node_flag_error(node, mpack_error_type);
  4656. }
  4657. size_t mpack_node_copy_data(mpack_node_t node, char* buffer, size_t bufsize) {
  4658. if (mpack_node_error(node) != mpack_ok)
  4659. return 0;
  4660. mpack_assert(bufsize == 0 || buffer != NULL, "buffer is NULL for maximum of %i bytes", (int)bufsize);
  4661. mpack_type_t type = node.data->type;
  4662. if (type != mpack_type_str && type != mpack_type_bin
  4663. #if MPACK_EXTENSIONS
  4664. && type != mpack_type_ext
  4665. #endif
  4666. ) {
  4667. mpack_node_flag_error(node, mpack_error_type);
  4668. return 0;
  4669. }
  4670. if (node.data->len > bufsize) {
  4671. mpack_node_flag_error(node, mpack_error_too_big);
  4672. return 0;
  4673. }
  4674. mpack_memcpy(buffer, mpack_node_data_unchecked(node), node.data->len);
  4675. return (size_t)node.data->len;
  4676. }
  4677. size_t mpack_node_copy_utf8(mpack_node_t node, char* buffer, size_t bufsize) {
  4678. if (mpack_node_error(node) != mpack_ok)
  4679. return 0;
  4680. mpack_assert(bufsize == 0 || buffer != NULL, "buffer is NULL for maximum of %i bytes", (int)bufsize);
  4681. mpack_type_t type = node.data->type;
  4682. if (type != mpack_type_str) {
  4683. mpack_node_flag_error(node, mpack_error_type);
  4684. return 0;
  4685. }
  4686. if (node.data->len > bufsize) {
  4687. mpack_node_flag_error(node, mpack_error_too_big);
  4688. return 0;
  4689. }
  4690. if (!mpack_utf8_check(mpack_node_data_unchecked(node), node.data->len)) {
  4691. mpack_node_flag_error(node, mpack_error_type);
  4692. return 0;
  4693. }
  4694. mpack_memcpy(buffer, mpack_node_data_unchecked(node), node.data->len);
  4695. return (size_t)node.data->len;
  4696. }
  4697. void mpack_node_copy_cstr(mpack_node_t node, char* buffer, size_t bufsize) {
  4698. // we can't break here because the error isn't recoverable; we
  4699. // have to add a null-terminator.
  4700. mpack_assert(buffer != NULL, "buffer is NULL");
  4701. mpack_assert(bufsize >= 1, "buffer size is zero; you must have room for at least a null-terminator");
  4702. if (mpack_node_error(node) != mpack_ok) {
  4703. buffer[0] = '\0';
  4704. return;
  4705. }
  4706. if (node.data->type != mpack_type_str) {
  4707. buffer[0] = '\0';
  4708. mpack_node_flag_error(node, mpack_error_type);
  4709. return;
  4710. }
  4711. if (node.data->len > bufsize - 1) {
  4712. buffer[0] = '\0';
  4713. mpack_node_flag_error(node, mpack_error_too_big);
  4714. return;
  4715. }
  4716. if (!mpack_str_check_no_null(mpack_node_data_unchecked(node), node.data->len)) {
  4717. buffer[0] = '\0';
  4718. mpack_node_flag_error(node, mpack_error_type);
  4719. return;
  4720. }
  4721. mpack_memcpy(buffer, mpack_node_data_unchecked(node), node.data->len);
  4722. buffer[node.data->len] = '\0';
  4723. }
  4724. void mpack_node_copy_utf8_cstr(mpack_node_t node, char* buffer, size_t bufsize) {
  4725. // we can't break here because the error isn't recoverable; we
  4726. // have to add a null-terminator.
  4727. mpack_assert(buffer != NULL, "buffer is NULL");
  4728. mpack_assert(bufsize >= 1, "buffer size is zero; you must have room for at least a null-terminator");
  4729. if (mpack_node_error(node) != mpack_ok) {
  4730. buffer[0] = '\0';
  4731. return;
  4732. }
  4733. if (node.data->type != mpack_type_str) {
  4734. buffer[0] = '\0';
  4735. mpack_node_flag_error(node, mpack_error_type);
  4736. return;
  4737. }
  4738. if (node.data->len > bufsize - 1) {
  4739. buffer[0] = '\0';
  4740. mpack_node_flag_error(node, mpack_error_too_big);
  4741. return;
  4742. }
  4743. if (!mpack_utf8_check_no_null(mpack_node_data_unchecked(node), node.data->len)) {
  4744. buffer[0] = '\0';
  4745. mpack_node_flag_error(node, mpack_error_type);
  4746. return;
  4747. }
  4748. mpack_memcpy(buffer, mpack_node_data_unchecked(node), node.data->len);
  4749. buffer[node.data->len] = '\0';
  4750. }
  4751. #ifdef MPACK_MALLOC
  4752. char* mpack_node_data_alloc(mpack_node_t node, size_t maxlen) {
  4753. if (mpack_node_error(node) != mpack_ok)
  4754. return NULL;
  4755. // make sure this is a valid data type
  4756. mpack_type_t type = node.data->type;
  4757. if (type != mpack_type_str && type != mpack_type_bin
  4758. #if MPACK_EXTENSIONS
  4759. && type != mpack_type_ext
  4760. #endif
  4761. ) {
  4762. mpack_node_flag_error(node, mpack_error_type);
  4763. return NULL;
  4764. }
  4765. if (node.data->len > maxlen) {
  4766. mpack_node_flag_error(node, mpack_error_too_big);
  4767. return NULL;
  4768. }
  4769. char* ret = (char*) MPACK_MALLOC((size_t)node.data->len);
  4770. if (ret == NULL) {
  4771. mpack_node_flag_error(node, mpack_error_memory);
  4772. return NULL;
  4773. }
  4774. mpack_memcpy(ret, mpack_node_data_unchecked(node), node.data->len);
  4775. return ret;
  4776. }
  4777. char* mpack_node_cstr_alloc(mpack_node_t node, size_t maxlen) {
  4778. if (mpack_node_error(node) != mpack_ok)
  4779. return NULL;
  4780. // make sure maxlen makes sense
  4781. if (maxlen < 1) {
  4782. mpack_break("maxlen is zero; you must have room for at least a null-terminator");
  4783. mpack_node_flag_error(node, mpack_error_bug);
  4784. return NULL;
  4785. }
  4786. if (node.data->type != mpack_type_str) {
  4787. mpack_node_flag_error(node, mpack_error_type);
  4788. return NULL;
  4789. }
  4790. if (node.data->len > maxlen - 1) {
  4791. mpack_node_flag_error(node, mpack_error_too_big);
  4792. return NULL;
  4793. }
  4794. if (!mpack_str_check_no_null(mpack_node_data_unchecked(node), node.data->len)) {
  4795. mpack_node_flag_error(node, mpack_error_type);
  4796. return NULL;
  4797. }
  4798. char* ret = (char*) MPACK_MALLOC((size_t)(node.data->len + 1));
  4799. if (ret == NULL) {
  4800. mpack_node_flag_error(node, mpack_error_memory);
  4801. return NULL;
  4802. }
  4803. mpack_memcpy(ret, mpack_node_data_unchecked(node), node.data->len);
  4804. ret[node.data->len] = '\0';
  4805. return ret;
  4806. }
  4807. char* mpack_node_utf8_cstr_alloc(mpack_node_t node, size_t maxlen) {
  4808. if (mpack_node_error(node) != mpack_ok)
  4809. return NULL;
  4810. // make sure maxlen makes sense
  4811. if (maxlen < 1) {
  4812. mpack_break("maxlen is zero; you must have room for at least a null-terminator");
  4813. mpack_node_flag_error(node, mpack_error_bug);
  4814. return NULL;
  4815. }
  4816. if (node.data->type != mpack_type_str) {
  4817. mpack_node_flag_error(node, mpack_error_type);
  4818. return NULL;
  4819. }
  4820. if (node.data->len > maxlen - 1) {
  4821. mpack_node_flag_error(node, mpack_error_too_big);
  4822. return NULL;
  4823. }
  4824. if (!mpack_utf8_check_no_null(mpack_node_data_unchecked(node), node.data->len)) {
  4825. mpack_node_flag_error(node, mpack_error_type);
  4826. return NULL;
  4827. }
  4828. char* ret = (char*) MPACK_MALLOC((size_t)(node.data->len + 1));
  4829. if (ret == NULL) {
  4830. mpack_node_flag_error(node, mpack_error_memory);
  4831. return NULL;
  4832. }
  4833. mpack_memcpy(ret, mpack_node_data_unchecked(node), node.data->len);
  4834. ret[node.data->len] = '\0';
  4835. return ret;
  4836. }
  4837. #endif
  4838. /*
  4839. * Compound Node Functions
  4840. */
  4841. static mpack_node_data_t* mpack_node_map_int_impl(mpack_node_t node, int64_t num) {
  4842. if (mpack_node_error(node) != mpack_ok)
  4843. return NULL;
  4844. if (node.data->type != mpack_type_map) {
  4845. mpack_node_flag_error(node, mpack_error_type);
  4846. return NULL;
  4847. }
  4848. mpack_node_data_t* found = NULL;
  4849. for (size_t i = 0; i < node.data->len; ++i) {
  4850. mpack_node_data_t* key = mpack_node_child(node, i * 2);
  4851. if ((key->type == mpack_type_int && key->value.i == num) ||
  4852. (key->type == mpack_type_uint && num >= 0 && key->value.u == (uint64_t)num))
  4853. {
  4854. if (found) {
  4855. mpack_node_flag_error(node, mpack_error_data);
  4856. return NULL;
  4857. }
  4858. found = mpack_node_child(node, i * 2 + 1);
  4859. }
  4860. }
  4861. if (found)
  4862. return found;
  4863. return NULL;
  4864. }
  4865. static mpack_node_data_t* mpack_node_map_uint_impl(mpack_node_t node, uint64_t num) {
  4866. if (mpack_node_error(node) != mpack_ok)
  4867. return NULL;
  4868. if (node.data->type != mpack_type_map) {
  4869. mpack_node_flag_error(node, mpack_error_type);
  4870. return NULL;
  4871. }
  4872. mpack_node_data_t* found = NULL;
  4873. for (size_t i = 0; i < node.data->len; ++i) {
  4874. mpack_node_data_t* key = mpack_node_child(node, i * 2);
  4875. if ((key->type == mpack_type_uint && key->value.u == num) ||
  4876. (key->type == mpack_type_int && key->value.i >= 0 && (uint64_t)key->value.i == num))
  4877. {
  4878. if (found) {
  4879. mpack_node_flag_error(node, mpack_error_data);
  4880. return NULL;
  4881. }
  4882. found = mpack_node_child(node, i * 2 + 1);
  4883. }
  4884. }
  4885. if (found)
  4886. return found;
  4887. return NULL;
  4888. }
  4889. static mpack_node_data_t* mpack_node_map_str_impl(mpack_node_t node, const char* str, size_t length) {
  4890. if (mpack_node_error(node) != mpack_ok)
  4891. return NULL;
  4892. mpack_assert(length == 0 || str != NULL, "str of length %i is NULL", (int)length);
  4893. if (node.data->type != mpack_type_map) {
  4894. mpack_node_flag_error(node, mpack_error_type);
  4895. return NULL;
  4896. }
  4897. mpack_tree_t* tree = node.tree;
  4898. mpack_node_data_t* found = NULL;
  4899. for (size_t i = 0; i < node.data->len; ++i) {
  4900. mpack_node_data_t* key = mpack_node_child(node, i * 2);
  4901. if (key->type == mpack_type_str && key->len == length &&
  4902. mpack_memcmp(str, mpack_node_data_unchecked(mpack_node(tree, key)), length) == 0) {
  4903. if (found) {
  4904. mpack_node_flag_error(node, mpack_error_data);
  4905. return NULL;
  4906. }
  4907. found = mpack_node_child(node, i * 2 + 1);
  4908. }
  4909. }
  4910. if (found)
  4911. return found;
  4912. return NULL;
  4913. }
  4914. static mpack_node_t mpack_node_wrap_lookup(mpack_tree_t* tree, mpack_node_data_t* data) {
  4915. if (!data) {
  4916. if (tree->error == mpack_ok)
  4917. mpack_tree_flag_error(tree, mpack_error_data);
  4918. return mpack_tree_nil_node(tree);
  4919. }
  4920. return mpack_node(tree, data);
  4921. }
  4922. static mpack_node_t mpack_node_wrap_lookup_optional(mpack_tree_t* tree, mpack_node_data_t* data) {
  4923. if (!data) {
  4924. if (tree->error == mpack_ok)
  4925. return mpack_tree_missing_node(tree);
  4926. return mpack_tree_nil_node(tree);
  4927. }
  4928. return mpack_node(tree, data);
  4929. }
  4930. mpack_node_t mpack_node_map_int(mpack_node_t node, int64_t num) {
  4931. return mpack_node_wrap_lookup(node.tree, mpack_node_map_int_impl(node, num));
  4932. }
  4933. mpack_node_t mpack_node_map_int_optional(mpack_node_t node, int64_t num) {
  4934. return mpack_node_wrap_lookup_optional(node.tree, mpack_node_map_int_impl(node, num));
  4935. }
  4936. mpack_node_t mpack_node_map_uint(mpack_node_t node, uint64_t num) {
  4937. return mpack_node_wrap_lookup(node.tree, mpack_node_map_uint_impl(node, num));
  4938. }
  4939. mpack_node_t mpack_node_map_uint_optional(mpack_node_t node, uint64_t num) {
  4940. return mpack_node_wrap_lookup_optional(node.tree, mpack_node_map_uint_impl(node, num));
  4941. }
  4942. mpack_node_t mpack_node_map_str(mpack_node_t node, const char* str, size_t length) {
  4943. return mpack_node_wrap_lookup(node.tree, mpack_node_map_str_impl(node, str, length));
  4944. }
  4945. mpack_node_t mpack_node_map_str_optional(mpack_node_t node, const char* str, size_t length) {
  4946. return mpack_node_wrap_lookup_optional(node.tree, mpack_node_map_str_impl(node, str, length));
  4947. }
  4948. mpack_node_t mpack_node_map_cstr(mpack_node_t node, const char* cstr) {
  4949. mpack_assert(cstr != NULL, "cstr is NULL");
  4950. return mpack_node_map_str(node, cstr, mpack_strlen(cstr));
  4951. }
  4952. mpack_node_t mpack_node_map_cstr_optional(mpack_node_t node, const char* cstr) {
  4953. mpack_assert(cstr != NULL, "cstr is NULL");
  4954. return mpack_node_map_str_optional(node, cstr, mpack_strlen(cstr));
  4955. }
  4956. bool mpack_node_map_contains_int(mpack_node_t node, int64_t num) {
  4957. return mpack_node_map_int_impl(node, num) != NULL;
  4958. }
  4959. bool mpack_node_map_contains_uint(mpack_node_t node, uint64_t num) {
  4960. return mpack_node_map_uint_impl(node, num) != NULL;
  4961. }
  4962. bool mpack_node_map_contains_str(mpack_node_t node, const char* str, size_t length) {
  4963. return mpack_node_map_str_impl(node, str, length) != NULL;
  4964. }
  4965. bool mpack_node_map_contains_cstr(mpack_node_t node, const char* cstr) {
  4966. mpack_assert(cstr != NULL, "cstr is NULL");
  4967. return mpack_node_map_contains_str(node, cstr, mpack_strlen(cstr));
  4968. }
  4969. size_t mpack_node_enum_optional(mpack_node_t node, const char* strings[], size_t count) {
  4970. if (mpack_node_error(node) != mpack_ok)
  4971. return count;
  4972. // the value is only recognized if it is a string
  4973. if (mpack_node_type(node) != mpack_type_str)
  4974. return count;
  4975. // fetch the string
  4976. const char* key = mpack_node_str(node);
  4977. size_t keylen = mpack_node_strlen(node);
  4978. mpack_assert(mpack_node_error(node) == mpack_ok, "these should not fail");
  4979. // find what key it matches
  4980. for (size_t i = 0; i < count; ++i) {
  4981. const char* other = strings[i];
  4982. size_t otherlen = mpack_strlen(other);
  4983. if (keylen == otherlen && mpack_memcmp(key, other, keylen) == 0)
  4984. return i;
  4985. }
  4986. // no matches
  4987. return count;
  4988. }
  4989. size_t mpack_node_enum(mpack_node_t node, const char* strings[], size_t count) {
  4990. size_t value = mpack_node_enum_optional(node, strings, count);
  4991. if (value == count)
  4992. mpack_node_flag_error(node, mpack_error_type);
  4993. return value;
  4994. }
  4995. mpack_type_t mpack_node_type(mpack_node_t node) {
  4996. if (mpack_node_error(node) != mpack_ok)
  4997. return mpack_type_nil;
  4998. return node.data->type;
  4999. }
  5000. bool mpack_node_is_nil(mpack_node_t node) {
  5001. if (mpack_node_error(node) != mpack_ok) {
  5002. // All nodes are treated as nil nodes when we are in error.
  5003. return true;
  5004. }
  5005. return node.data->type == mpack_type_nil;
  5006. }
  5007. bool mpack_node_is_missing(mpack_node_t node) {
  5008. if (mpack_node_error(node) != mpack_ok) {
  5009. // errors still return nil nodes, not missing nodes.
  5010. return false;
  5011. }
  5012. return node.data->type == mpack_type_missing;
  5013. }
  5014. void mpack_node_nil(mpack_node_t node) {
  5015. if (mpack_node_error(node) != mpack_ok)
  5016. return;
  5017. if (node.data->type != mpack_type_nil)
  5018. mpack_node_flag_error(node, mpack_error_type);
  5019. }
  5020. void mpack_node_missing(mpack_node_t node) {
  5021. if (mpack_node_error(node) != mpack_ok)
  5022. return;
  5023. if (node.data->type != mpack_type_missing)
  5024. mpack_node_flag_error(node, mpack_error_type);
  5025. }
  5026. bool mpack_node_bool(mpack_node_t node) {
  5027. if (mpack_node_error(node) != mpack_ok)
  5028. return false;
  5029. if (node.data->type == mpack_type_bool)
  5030. return node.data->value.b;
  5031. mpack_node_flag_error(node, mpack_error_type);
  5032. return false;
  5033. }
  5034. void mpack_node_true(mpack_node_t node) {
  5035. if (mpack_node_bool(node) != true)
  5036. mpack_node_flag_error(node, mpack_error_type);
  5037. }
  5038. void mpack_node_false(mpack_node_t node) {
  5039. if (mpack_node_bool(node) != false)
  5040. mpack_node_flag_error(node, mpack_error_type);
  5041. }
  5042. uint8_t mpack_node_u8(mpack_node_t node) {
  5043. if (mpack_node_error(node) != mpack_ok)
  5044. return 0;
  5045. if (node.data->type == mpack_type_uint) {
  5046. if (node.data->value.u <= UINT8_MAX)
  5047. return (uint8_t)node.data->value.u;
  5048. } else if (node.data->type == mpack_type_int) {
  5049. if (node.data->value.i >= 0 && node.data->value.i <= UINT8_MAX)
  5050. return (uint8_t)node.data->value.i;
  5051. }
  5052. mpack_node_flag_error(node, mpack_error_type);
  5053. return 0;
  5054. }
  5055. int8_t mpack_node_i8(mpack_node_t node) {
  5056. if (mpack_node_error(node) != mpack_ok)
  5057. return 0;
  5058. if (node.data->type == mpack_type_uint) {
  5059. if (node.data->value.u <= INT8_MAX)
  5060. return (int8_t)node.data->value.u;
  5061. } else if (node.data->type == mpack_type_int) {
  5062. if (node.data->value.i >= INT8_MIN && node.data->value.i <= INT8_MAX)
  5063. return (int8_t)node.data->value.i;
  5064. }
  5065. mpack_node_flag_error(node, mpack_error_type);
  5066. return 0;
  5067. }
  5068. uint16_t mpack_node_u16(mpack_node_t node) {
  5069. if (mpack_node_error(node) != mpack_ok)
  5070. return 0;
  5071. if (node.data->type == mpack_type_uint) {
  5072. if (node.data->value.u <= UINT16_MAX)
  5073. return (uint16_t)node.data->value.u;
  5074. } else if (node.data->type == mpack_type_int) {
  5075. if (node.data->value.i >= 0 && node.data->value.i <= UINT16_MAX)
  5076. return (uint16_t)node.data->value.i;
  5077. }
  5078. mpack_node_flag_error(node, mpack_error_type);
  5079. return 0;
  5080. }
  5081. int16_t mpack_node_i16(mpack_node_t node) {
  5082. if (mpack_node_error(node) != mpack_ok)
  5083. return 0;
  5084. if (node.data->type == mpack_type_uint) {
  5085. if (node.data->value.u <= INT16_MAX)
  5086. return (int16_t)node.data->value.u;
  5087. } else if (node.data->type == mpack_type_int) {
  5088. if (node.data->value.i >= INT16_MIN && node.data->value.i <= INT16_MAX)
  5089. return (int16_t)node.data->value.i;
  5090. }
  5091. mpack_node_flag_error(node, mpack_error_type);
  5092. return 0;
  5093. }
  5094. uint32_t mpack_node_u32(mpack_node_t node) {
  5095. if (mpack_node_error(node) != mpack_ok)
  5096. return 0;
  5097. if (node.data->type == mpack_type_uint) {
  5098. if (node.data->value.u <= UINT32_MAX)
  5099. return (uint32_t)node.data->value.u;
  5100. } else if (node.data->type == mpack_type_int) {
  5101. if (node.data->value.i >= 0 && node.data->value.i <= UINT32_MAX)
  5102. return (uint32_t)node.data->value.i;
  5103. }
  5104. mpack_node_flag_error(node, mpack_error_type);
  5105. return 0;
  5106. }
  5107. int32_t mpack_node_i32(mpack_node_t node) {
  5108. if (mpack_node_error(node) != mpack_ok)
  5109. return 0;
  5110. if (node.data->type == mpack_type_uint) {
  5111. if (node.data->value.u <= INT32_MAX)
  5112. return (int32_t)node.data->value.u;
  5113. } else if (node.data->type == mpack_type_int) {
  5114. if (node.data->value.i >= INT32_MIN && node.data->value.i <= INT32_MAX)
  5115. return (int32_t)node.data->value.i;
  5116. }
  5117. mpack_node_flag_error(node, mpack_error_type);
  5118. return 0;
  5119. }
  5120. uint64_t mpack_node_u64(mpack_node_t node) {
  5121. if (mpack_node_error(node) != mpack_ok)
  5122. return 0;
  5123. if (node.data->type == mpack_type_uint) {
  5124. return node.data->value.u;
  5125. } else if (node.data->type == mpack_type_int) {
  5126. if (node.data->value.i >= 0)
  5127. return (uint64_t)node.data->value.i;
  5128. }
  5129. mpack_node_flag_error(node, mpack_error_type);
  5130. return 0;
  5131. }
  5132. int64_t mpack_node_i64(mpack_node_t node) {
  5133. if (mpack_node_error(node) != mpack_ok)
  5134. return 0;
  5135. if (node.data->type == mpack_type_uint) {
  5136. if (node.data->value.u <= (uint64_t)INT64_MAX)
  5137. return (int64_t)node.data->value.u;
  5138. } else if (node.data->type == mpack_type_int) {
  5139. return node.data->value.i;
  5140. }
  5141. mpack_node_flag_error(node, mpack_error_type);
  5142. return 0;
  5143. }
  5144. unsigned int mpack_node_uint(mpack_node_t node) {
  5145. // This should be true at compile-time, so this just wraps the 32-bit function.
  5146. if (sizeof(unsigned int) == 4)
  5147. return (unsigned int)mpack_node_u32(node);
  5148. // Otherwise we use u64 and check the range.
  5149. uint64_t val = mpack_node_u64(node);
  5150. if (val <= UINT_MAX)
  5151. return (unsigned int)val;
  5152. mpack_node_flag_error(node, mpack_error_type);
  5153. return 0;
  5154. }
  5155. int mpack_node_int(mpack_node_t node) {
  5156. // This should be true at compile-time, so this just wraps the 32-bit function.
  5157. if (sizeof(int) == 4)
  5158. return (int)mpack_node_i32(node);
  5159. // Otherwise we use i64 and check the range.
  5160. int64_t val = mpack_node_i64(node);
  5161. if (val >= INT_MIN && val <= INT_MAX)
  5162. return (int)val;
  5163. mpack_node_flag_error(node, mpack_error_type);
  5164. return 0;
  5165. }
  5166. float mpack_node_float(mpack_node_t node) {
  5167. if (mpack_node_error(node) != mpack_ok)
  5168. return 0.0f;
  5169. if (node.data->type == mpack_type_uint)
  5170. return (float)node.data->value.u;
  5171. else if (node.data->type == mpack_type_int)
  5172. return (float)node.data->value.i;
  5173. else if (node.data->type == mpack_type_float)
  5174. return node.data->value.f;
  5175. else if (node.data->type == mpack_type_double)
  5176. return (float)node.data->value.d;
  5177. mpack_node_flag_error(node, mpack_error_type);
  5178. return 0.0f;
  5179. }
  5180. double mpack_node_double(mpack_node_t node) {
  5181. if (mpack_node_error(node) != mpack_ok)
  5182. return 0.0;
  5183. if (node.data->type == mpack_type_uint)
  5184. return (double)node.data->value.u;
  5185. else if (node.data->type == mpack_type_int)
  5186. return (double)node.data->value.i;
  5187. else if (node.data->type == mpack_type_float)
  5188. return (double)node.data->value.f;
  5189. else if (node.data->type == mpack_type_double)
  5190. return node.data->value.d;
  5191. mpack_node_flag_error(node, mpack_error_type);
  5192. return 0.0;
  5193. }
  5194. float mpack_node_float_strict(mpack_node_t node) {
  5195. if (mpack_node_error(node) != mpack_ok)
  5196. return 0.0f;
  5197. if (node.data->type == mpack_type_float)
  5198. return node.data->value.f;
  5199. mpack_node_flag_error(node, mpack_error_type);
  5200. return 0.0f;
  5201. }
  5202. double mpack_node_double_strict(mpack_node_t node) {
  5203. if (mpack_node_error(node) != mpack_ok)
  5204. return 0.0;
  5205. if (node.data->type == mpack_type_float)
  5206. return (double)node.data->value.f;
  5207. else if (node.data->type == mpack_type_double)
  5208. return node.data->value.d;
  5209. mpack_node_flag_error(node, mpack_error_type);
  5210. return 0.0;
  5211. }
  5212. #if MPACK_EXTENSIONS
  5213. int8_t mpack_node_exttype(mpack_node_t node) {
  5214. if (mpack_node_error(node) != mpack_ok)
  5215. return 0;
  5216. if (node.data->type == mpack_type_ext)
  5217. return mpack_node_exttype_unchecked(node);
  5218. mpack_node_flag_error(node, mpack_error_type);
  5219. return 0;
  5220. }
  5221. #endif
  5222. uint32_t mpack_node_data_len(mpack_node_t node) {
  5223. if (mpack_node_error(node) != mpack_ok)
  5224. return 0;
  5225. mpack_type_t type = node.data->type;
  5226. if (type == mpack_type_str || type == mpack_type_bin
  5227. #if MPACK_EXTENSIONS
  5228. || type == mpack_type_ext
  5229. #endif
  5230. )
  5231. return (uint32_t)node.data->len;
  5232. mpack_node_flag_error(node, mpack_error_type);
  5233. return 0;
  5234. }
  5235. size_t mpack_node_strlen(mpack_node_t node) {
  5236. if (mpack_node_error(node) != mpack_ok)
  5237. return 0;
  5238. if (node.data->type == mpack_type_str)
  5239. return (size_t)node.data->len;
  5240. mpack_node_flag_error(node, mpack_error_type);
  5241. return 0;
  5242. }
  5243. const char* mpack_node_str(mpack_node_t node) {
  5244. if (mpack_node_error(node) != mpack_ok)
  5245. return NULL;
  5246. mpack_type_t type = node.data->type;
  5247. if (type == mpack_type_str)
  5248. return mpack_node_data_unchecked(node);
  5249. mpack_node_flag_error(node, mpack_error_type);
  5250. return NULL;
  5251. }
  5252. const char* mpack_node_data(mpack_node_t node) {
  5253. if (mpack_node_error(node) != mpack_ok)
  5254. return NULL;
  5255. mpack_type_t type = node.data->type;
  5256. if (type == mpack_type_str || type == mpack_type_bin
  5257. #if MPACK_EXTENSIONS
  5258. || type == mpack_type_ext
  5259. #endif
  5260. )
  5261. return mpack_node_data_unchecked(node);
  5262. mpack_node_flag_error(node, mpack_error_type);
  5263. return NULL;
  5264. }
  5265. const char* mpack_node_bin_data(mpack_node_t node) {
  5266. if (mpack_node_error(node) != mpack_ok)
  5267. return NULL;
  5268. if (node.data->type == mpack_type_bin)
  5269. return mpack_node_data_unchecked(node);
  5270. mpack_node_flag_error(node, mpack_error_type);
  5271. return NULL;
  5272. }
  5273. size_t mpack_node_bin_size(mpack_node_t node) {
  5274. if (mpack_node_error(node) != mpack_ok)
  5275. return 0;
  5276. if (node.data->type == mpack_type_bin)
  5277. return (size_t)node.data->len;
  5278. mpack_node_flag_error(node, mpack_error_type);
  5279. return 0;
  5280. }
  5281. size_t mpack_node_array_length(mpack_node_t node) {
  5282. if (mpack_node_error(node) != mpack_ok)
  5283. return 0;
  5284. if (node.data->type != mpack_type_array) {
  5285. mpack_node_flag_error(node, mpack_error_type);
  5286. return 0;
  5287. }
  5288. return (size_t)node.data->len;
  5289. }
  5290. mpack_node_t mpack_node_array_at(mpack_node_t node, size_t index) {
  5291. if (mpack_node_error(node) != mpack_ok)
  5292. return mpack_tree_nil_node(node.tree);
  5293. if (node.data->type != mpack_type_array) {
  5294. mpack_node_flag_error(node, mpack_error_type);
  5295. return mpack_tree_nil_node(node.tree);
  5296. }
  5297. if (index >= node.data->len) {
  5298. mpack_node_flag_error(node, mpack_error_data);
  5299. return mpack_tree_nil_node(node.tree);
  5300. }
  5301. return mpack_node(node.tree, mpack_node_child(node, index));
  5302. }
  5303. size_t mpack_node_map_count(mpack_node_t node) {
  5304. if (mpack_node_error(node) != mpack_ok)
  5305. return 0;
  5306. if (node.data->type != mpack_type_map) {
  5307. mpack_node_flag_error(node, mpack_error_type);
  5308. return 0;
  5309. }
  5310. return node.data->len;
  5311. }
  5312. // internal node map lookup
  5313. static mpack_node_t mpack_node_map_at(mpack_node_t node, size_t index, size_t offset) {
  5314. if (mpack_node_error(node) != mpack_ok)
  5315. return mpack_tree_nil_node(node.tree);
  5316. if (node.data->type != mpack_type_map) {
  5317. mpack_node_flag_error(node, mpack_error_type);
  5318. return mpack_tree_nil_node(node.tree);
  5319. }
  5320. if (index >= node.data->len) {
  5321. mpack_node_flag_error(node, mpack_error_data);
  5322. return mpack_tree_nil_node(node.tree);
  5323. }
  5324. return mpack_node(node.tree, mpack_node_child(node, index * 2 + offset));
  5325. }
  5326. mpack_node_t mpack_node_map_key_at(mpack_node_t node, size_t index) {
  5327. return mpack_node_map_at(node, index, 0);
  5328. }
  5329. mpack_node_t mpack_node_map_value_at(mpack_node_t node, size_t index) {
  5330. return mpack_node_map_at(node, index, 1);
  5331. }
  5332. #endif