2424 */
2525
2626/*
27- * This is the MPack 1.1 amalgamation package.
27+ * This is the MPack 1.1.1 amalgamation package.
2828 *
2929 * http://github.com/ludocode/mpack
3030 */
@@ -424,7 +424,7 @@ static void mpack_tag_debug_pseudo_json_bin(mpack_tag_t tag, char* buffer, size_
424424 const char * prefix , size_t prefix_size )
425425{
426426 mpack_assert (mpack_tag_type (& tag ) == mpack_type_bin );
427- size_t length = (size_t )mpack_snprintf (buffer , buffer_size , "<binary data of length %u " , tag .v .l );
427+ size_t length = (size_t )mpack_snprintf (buffer , buffer_size , "<binary data of length %" PRIu32 " " , tag .v .l );
428428 mpack_tag_debug_complete_bin_ext (tag , length , buffer , buffer_size , prefix , prefix_size );
429429}
430430
@@ -433,7 +433,7 @@ static void mpack_tag_debug_pseudo_json_ext(mpack_tag_t tag, char* buffer, size_
433433 const char * prefix , size_t prefix_size )
434434{
435435 mpack_assert (mpack_tag_type (& tag ) == mpack_type_ext );
436- size_t length = (size_t )mpack_snprintf (buffer , buffer_size , "<ext data of type %i and length %u " ,
436+ size_t length = (size_t )mpack_snprintf (buffer , buffer_size , "<ext data of type %i and length %" PRIu32 " " ,
437437 mpack_tag_ext_exttype (& tag ), mpack_tag_ext_length (& tag ));
438438 mpack_tag_debug_complete_bin_ext (tag , length , buffer , buffer_size , prefix , prefix_size );
439439}
@@ -474,7 +474,7 @@ static void mpack_tag_debug_pseudo_json_impl(mpack_tag_t tag, char* buffer, size
474474 return ;
475475
476476 case mpack_type_str :
477- mpack_snprintf (buffer , buffer_size , "<string of %u bytes>" , tag .v .l );
477+ mpack_snprintf (buffer , buffer_size , "<string of %" PRIu32 " bytes>" , tag .v .l );
478478 return ;
479479 case mpack_type_bin :
480480 mpack_tag_debug_pseudo_json_bin (tag , buffer , buffer_size , prefix , prefix_size );
@@ -486,10 +486,10 @@ static void mpack_tag_debug_pseudo_json_impl(mpack_tag_t tag, char* buffer, size
486486 #endif
487487
488488 case mpack_type_array :
489- mpack_snprintf (buffer , buffer_size , "<array of %u elements>" , tag .v .n );
489+ mpack_snprintf (buffer , buffer_size , "<array of %" PRIu32 " elements>" , tag .v .n );
490490 return ;
491491 case mpack_type_map :
492- mpack_snprintf (buffer , buffer_size , "<map of %u key-value pairs>" , tag .v .n );
492+ mpack_snprintf (buffer , buffer_size , "<map of %" PRIu32 " key-value pairs>" , tag .v .n );
493493 return ;
494494 }
495495
@@ -541,22 +541,22 @@ static void mpack_tag_debug_describe_impl(mpack_tag_t tag, char* buffer, size_t
541541 #endif
542542 return ;
543543 case mpack_type_str :
544- mpack_snprintf (buffer , buffer_size , "str of %u bytes" , tag .v .l );
544+ mpack_snprintf (buffer , buffer_size , "str of %" PRIu32 " bytes" , tag .v .l );
545545 return ;
546546 case mpack_type_bin :
547- mpack_snprintf (buffer , buffer_size , "bin of %u bytes" , tag .v .l );
547+ mpack_snprintf (buffer , buffer_size , "bin of %" PRIu32 " bytes" , tag .v .l );
548548 return ;
549549 #if MPACK_EXTENSIONS
550550 case mpack_type_ext :
551- mpack_snprintf (buffer , buffer_size , "ext of type %i, %u bytes" ,
551+ mpack_snprintf (buffer , buffer_size , "ext of type %i, %" PRIu32 " bytes" ,
552552 mpack_tag_ext_exttype (& tag ), mpack_tag_ext_length (& tag ));
553553 return ;
554554 #endif
555555 case mpack_type_array :
556- mpack_snprintf (buffer , buffer_size , "array of %u elements" , tag .v .n );
556+ mpack_snprintf (buffer , buffer_size , "array of %" PRIu32 " elements" , tag .v .n );
557557 return ;
558558 case mpack_type_map :
559- mpack_snprintf (buffer , buffer_size , "map of %u key-value pairs" , tag .v .n );
559+ mpack_snprintf (buffer , buffer_size , "map of %" PRIu32 " key-value pairs" , tag .v .n );
560560 return ;
561561 }
562562
@@ -1034,7 +1034,7 @@ static inline void mpack_writer_track_element(mpack_writer_t* writer) {
10341034 if (build -> nested_compound_elements == 0 ) {
10351035 if (build -> type != mpack_type_map ) {
10361036 ++ build -> count ;
1037- mpack_log ("adding element to build %p, now %u elements\n" , (void * )build , build -> count );
1037+ mpack_log ("adding element to build %p, now %" PRIu32 " elements\n" , (void * )build , build -> count );
10381038 } else if (build -> key_needs_value ) {
10391039 build -> key_needs_value = false;
10401040 ++ build -> count ;
@@ -1489,6 +1489,46 @@ mpack_error_t mpack_writer_destroy(mpack_writer_t* writer) {
14891489 mpack_track_destroy (& writer -> track , writer -> error != mpack_ok );
14901490 #endif
14911491
1492+ #if MPACK_BUILDER
1493+ mpack_builder_t * builder = & writer -> builder ;
1494+ if (builder -> current_build != NULL ) {
1495+ // A builder is open!
1496+
1497+ // Flag an error, if there's not already an error. You can only skip
1498+ // closing any open compound types if a write error occurred. If there
1499+ // wasn't already an error, it's a bug, which will assert in debug.
1500+ if (mpack_writer_error (writer ) == mpack_ok ) {
1501+ mpack_break ("writer cannot be destroyed with an incomplete builder unless "
1502+ "an error was flagged!" );
1503+ mpack_writer_flag_error (writer , mpack_error_bug );
1504+ }
1505+
1506+ // Free any remaining builder pages
1507+ mpack_builder_page_t * page = builder -> pages ;
1508+ #if MPACK_BUILDER_INTERNAL_STORAGE
1509+ mpack_assert (page == (mpack_builder_page_t * )builder -> internal );
1510+ page = page -> next ;
1511+ #endif
1512+ while (page != NULL ) {
1513+ mpack_builder_page_t * next = page -> next ;
1514+ MPACK_FREE (page );
1515+ page = next ;
1516+ }
1517+
1518+ // Restore the stashed pointers. The teardown function may need to free
1519+ // them (e.g. mpack_growable_writer_teardown().)
1520+ writer -> buffer = builder -> stash_buffer ;
1521+ writer -> position = builder -> stash_position ;
1522+ writer -> end = builder -> stash_end ;
1523+
1524+ // Note: It's not necessary to clean up the current_build or other
1525+ // pointers at this point because we're guaranteed to be in an error
1526+ // state already so a user error callback can't longjmp out. This
1527+ // destroy function will complete no matter what so it doesn't matter
1528+ // what junk is left in the writer.
1529+ }
1530+ #endif
1531+
14921532 // flush any outstanding data
14931533 if (mpack_writer_error (writer ) == mpack_ok && mpack_writer_buffer_used (writer ) != 0 && writer -> flush != NULL ) {
14941534 writer -> flush (writer , writer -> buffer , mpack_writer_buffer_used (writer ));
@@ -2017,7 +2057,7 @@ void mpack_write_timestamp(mpack_writer_t* writer, int64_t seconds, uint32_t nan
20172057 #endif
20182058
20192059 if (nanoseconds > MPACK_TIMESTAMP_NANOSECONDS_MAX ) {
2020- mpack_break ("timestamp nanoseconds out of bounds: %u" , nanoseconds );
2060+ mpack_break ("timestamp nanoseconds out of bounds: %" PRIu32 , nanoseconds );
20212061 mpack_writer_flag_error (writer , mpack_error_bug );
20222062 return ;
20232063 }
@@ -2160,7 +2200,7 @@ void mpack_start_ext(mpack_writer_t* writer, int8_t exttype, uint32_t count) {
21602200 */
21612201
21622202void mpack_write_str (mpack_writer_t * writer , const char * data , uint32_t count ) {
2163- mpack_assert (data != NULL , "data for string of length %i is NULL" , (int )count );
2203+ mpack_assert (count == 0 || data != NULL , "data for string of length %i is NULL" , (int )count );
21642204
21652205 #if MPACK_OPTIMIZE_FOR_SIZE
21662206 mpack_writer_track_element (writer );
@@ -2215,23 +2255,23 @@ void mpack_write_str(mpack_writer_t* writer, const char* data, uint32_t count) {
22152255}
22162256
22172257void mpack_write_bin (mpack_writer_t * writer , const char * data , uint32_t count ) {
2218- mpack_assert (data != NULL , "data pointer for bin of %i bytes is NULL" , (int )count );
2258+ mpack_assert (count == 0 || data != NULL , "data pointer for bin of %i bytes is NULL" , (int )count );
22192259 mpack_start_bin (writer , count );
22202260 mpack_write_bytes (writer , data , count );
22212261 mpack_finish_bin (writer );
22222262}
22232263
22242264#if MPACK_EXTENSIONS
22252265void mpack_write_ext (mpack_writer_t * writer , int8_t exttype , const char * data , uint32_t count ) {
2226- mpack_assert (data != NULL , "data pointer for ext of type %i and %i bytes is NULL" , exttype , (int )count );
2266+ mpack_assert (count == 0 || data != NULL , "data pointer for ext of type %i and %i bytes is NULL" , exttype , (int )count );
22272267 mpack_start_ext (writer , exttype , count );
22282268 mpack_write_bytes (writer , data , count );
22292269 mpack_finish_ext (writer );
22302270}
22312271#endif
22322272
22332273void mpack_write_bytes (mpack_writer_t * writer , const char * data , size_t count ) {
2234- mpack_assert (data != NULL , "data pointer for %i bytes is NULL" , (int )count );
2274+ mpack_assert (count == 0 || data != NULL , "data pointer for %i bytes is NULL" , (int )count );
22352275 mpack_writer_track_bytes (writer , count );
22362276 mpack_write_native (writer , data , count );
22372277}
@@ -2252,7 +2292,7 @@ void mpack_write_cstr_or_nil(mpack_writer_t* writer, const char* cstr) {
22522292}
22532293
22542294void mpack_write_utf8 (mpack_writer_t * writer , const char * str , uint32_t length ) {
2255- mpack_assert (str != NULL , "data for string of length %i is NULL" , (int )length );
2295+ mpack_assert (length == 0 || str != NULL , "data for string of length %i is NULL" , (int )length );
22562296 if (!mpack_utf8_check (str , length )) {
22572297 mpack_writer_flag_error (writer , mpack_error_invalid );
22582298 return ;
@@ -2552,6 +2592,16 @@ MPACK_NOINLINE
25522592static void mpack_builder_resolve (mpack_writer_t * writer ) {
25532593 mpack_builder_t * builder = & writer -> builder ;
25542594
2595+ // We should not have gotten here if we are in an error state. If an error
2596+ // occurs with an open builder, the writer will free the open builder pages
2597+ // when destroyed.
2598+ mpack_assert (mpack_writer_error (writer ) == mpack_ok , "can't resolve in error state!" );
2599+
2600+ // We don't want the user to longjmp out of any I/O errors while we are
2601+ // walking the page list, so defer error callbacks to after we're done.
2602+ mpack_writer_error_t error_fn = writer -> error_fn ;
2603+ writer -> error_fn = NULL ;
2604+
25552605 // The starting page is the internal storage (if we have it), otherwise
25562606 // it's the first page in the array
25572607 mpack_builder_page_t * page =
@@ -2584,13 +2634,13 @@ static void mpack_builder_resolve(mpack_writer_t* writer) {
25842634
25852635 // Walk the list of builds, writing everything out in the buffer. Note that
25862636 // we don't check for errors anywhere. The lower-level write functions will
2587- // all check for errors. We need to walk all pages anyway to free them, so
2588- // there's not much point in optimizing an error path at the expense of the
2589- // normal path.
2637+ // all check for errors and do nothing after an error occurs. We need to
2638+ // walk all pages anyway to free them, so there's not much point in
2639+ // optimizing an error path at the expense of the normal path.
25902640 while (true) {
25912641
25922642 // write out the container tag
2593- mpack_log ("writing out an %s with count %u followed by %zi bytes\n" ,
2643+ mpack_log ("writing out an %s with count %" PRIu32 " followed by %zi bytes\n" ,
25942644 mpack_type_to_string (build -> type ), build -> count , build -> bytes );
25952645 switch (build -> type ) {
25962646 case mpack_type_map :
@@ -2640,7 +2690,7 @@ static void mpack_builder_resolve(mpack_writer_t* writer) {
26402690
26412691 // now see if we can find another build.
26422692 offset = mpack_builder_align_build (offset );
2643- if (offset + sizeof (mpack_build_t ) >= mpack_builder_page_size (writer , page )) {
2693+ if (offset + sizeof (mpack_build_t ) > mpack_builder_page_size (writer , page )) {
26442694 mpack_log ("not enough room in this page for another build\n" );
26452695 mpack_builder_page_t * next_page = page -> next ;
26462696 mpack_builder_free_page (writer , page );
@@ -2666,13 +2716,18 @@ static void mpack_builder_resolve(mpack_writer_t* writer) {
26662716 }
26672717
26682718 mpack_log ("done resolve.\n" );
2719+
2720+ // We can now restore the error handler and call it if an error occurred.
2721+ writer -> error_fn = error_fn ;
2722+ if (writer -> error_fn && mpack_writer_error (writer ) != mpack_ok )
2723+ writer -> error_fn (writer , writer -> error );
26692724}
26702725
26712726static void mpack_builder_complete (mpack_writer_t * writer , mpack_type_t type ) {
2727+ mpack_writer_track_pop_builder (writer , type );
26722728 if (mpack_writer_error (writer ) != mpack_ok )
26732729 return ;
26742730
2675- mpack_writer_track_pop_builder (writer , type );
26762731 mpack_builder_t * builder = & writer -> builder ;
26772732 mpack_assert (builder -> current_build != NULL , "no build in progress!" );
26782733 mpack_assert (builder -> latest_build != NULL , "missing latest build!" );
@@ -3113,7 +3168,7 @@ void mpack_skip_bytes(mpack_reader_t* reader, size_t count) {
31133168 // check if we have enough in the buffer already
31143169 size_t left = (size_t )(reader -> end - reader -> data );
31153170 if (left >= count ) {
3116- mpack_log ("skipping %u bytes still in buffer\n" , (uint32_t )count );
3171+ mpack_log ("skipping %" PRIu32 " bytes still in buffer\n" , (uint32_t )count );
31173172 reader -> data += count ;
31183173 return ;
31193174 }
@@ -5002,7 +5057,7 @@ static bool mpack_tree_reserve_fill(mpack_tree_t* tree) {
50025057 return false;
50035058 }
50045059
5005- mpack_log ("read %u more bytes\n" , (uint32_t )read );
5060+ mpack_log ("read %" PRIu32 " more bytes\n" , (uint32_t )read );
50065061 tree -> data_length += read ;
50075062 tree -> parser .possible_nodes_left += read ;
50085063 } while (tree -> parser .possible_nodes_left < bytes );
0 commit comments