static void mpack_growable_writer_teardown(mpack_writer_t* writer) { mpack_growable_writer_t* growable_writer = (mpack_growable_writer_t*)writer->context; if (mpack_writer_error(writer) == mpack_ok) { // shrink the buffer to an appropriate size if the data is // much smaller than the buffer if (writer->used < writer->size / 2) { char* buffer = (char*)mpack_realloc(writer->buffer, writer->used, writer->used); if (!buffer) { MPACK_FREE(writer->buffer); mpack_writer_flag_error(writer, mpack_error_memory); return; } writer->buffer = buffer; writer->size = writer->used; } *growable_writer->target_data = writer->buffer; *growable_writer->target_size = writer->used; writer->buffer = NULL; } else if (writer->buffer) { MPACK_FREE(writer->buffer); writer->buffer = NULL; } writer->context = NULL; }
void* mpack_realloc(void* old_ptr, size_t used_size, size_t new_size) { if (new_size == 0) { if (old_ptr) MPACK_FREE(old_ptr); return NULL; } void* new_ptr = MPACK_MALLOC(new_size); if (new_ptr == NULL) return NULL; mpack_memcpy(new_ptr, old_ptr, used_size); MPACK_FREE(old_ptr); return new_ptr; }
char* mpack_read_bytes_alloc_impl(mpack_reader_t* reader, size_t count, bool null_terminated) { // track the bytes first in case it jumps mpack_reader_track_bytes(reader, count); if (mpack_reader_error(reader) != mpack_ok) return NULL; // cannot allocate zero bytes. this is not an error. if (count == 0 && null_terminated == false) return NULL; // allocate data char* data = (char*)MPACK_MALLOC(count + (null_terminated ? 1 : 0)); // TODO: can this overflow? if (data == NULL) { mpack_reader_flag_error(reader, mpack_error_memory); return NULL; } // read with error callback disabled so we don't leak our buffer mpack_read_native_noerrorfn(reader, data, count); // report flagged errors if (mpack_reader_error(reader) != mpack_ok) { MPACK_FREE(data); if (reader->error_fn) reader->error_fn(reader, mpack_reader_error(reader)); return NULL; } if (null_terminated) data[count] = '\0'; return data; }
void mpack_reader_init_file(mpack_reader_t* reader, const char* filename) { mpack_assert(filename != NULL, "filename is NULL"); size_t capacity = MPACK_BUFFER_SIZE; char* buffer = (char*)MPACK_MALLOC(capacity); if (buffer == NULL) { mpack_reader_init_error(reader, mpack_error_memory); return; } FILE* file = fopen(filename, "rb"); if (file == NULL) { MPACK_FREE(buffer); mpack_reader_init_error(reader, mpack_error_io); return; } mpack_reader_init(reader, buffer, capacity, 0); mpack_reader_set_context(reader, file); mpack_reader_set_fill(reader, mpack_file_reader_fill); #if !MPACK_OPTIMIZE_FOR_SIZE mpack_reader_set_skip(reader, mpack_file_reader_skip); #endif mpack_reader_set_teardown(reader, mpack_file_reader_teardown); }
mpack_error_t mpack_track_destroy(mpack_track_t* track, bool cancel) { mpack_error_t error = cancel ? mpack_ok : mpack_track_check_empty(track); if (track->elements) { MPACK_FREE(track->elements); track->elements = NULL; } return error; }
static void test_node_read_data(void) { static const char test[] = "\x93\xa5""alice\xc4\x03""bob\xd6\x07""carl"; mpack_tree_t tree; TEST_TREE_INIT(&tree, test, sizeof(test) - 1); mpack_node_t root = mpack_tree_root(&tree); mpack_node_t alice = mpack_node_array_at(root, 0); TEST_TRUE(5 == mpack_node_data_len(alice)); TEST_TRUE(5 == mpack_node_strlen(alice)); TEST_TRUE(NULL != mpack_node_data(alice)); TEST_TRUE(0 == memcmp("alice", mpack_node_data(alice), 5)); char alice_data[6] = {'s','s','s','s','s','s'}; mpack_node_copy_data(alice, alice_data, sizeof(alice_data)); TEST_TRUE(0 == memcmp("alices", alice_data, 6)); mpack_node_copy_cstr(alice, alice_data, sizeof(alice_data)); TEST_TRUE(0 == strcmp("alice", alice_data)); #ifdef MPACK_MALLOC char* alice_alloc = mpack_node_cstr_alloc(alice, 100); TEST_TRUE(0 == strcmp("alice", alice_alloc)); MPACK_FREE(alice_alloc); #endif mpack_node_t bob = mpack_node_array_at(root, 1); TEST_TRUE(3 == mpack_node_data_len(bob)); TEST_TRUE(0 == memcmp("bob", mpack_node_data(bob), 3)); #ifdef MPACK_MALLOC char* bob_alloc = mpack_node_data_alloc(bob, 100); TEST_TRUE(0 == memcmp("bob", bob_alloc, 3)); MPACK_FREE(bob_alloc); #endif mpack_node_t carl = mpack_node_array_at(root, 2); TEST_TRUE(7 == mpack_node_exttype(carl)); TEST_TRUE(4 == mpack_node_data_len(carl)); TEST_TRUE(0 == memcmp("carl", mpack_node_data(carl), 4)); TEST_TREE_DESTROY_NOERROR(&tree); }
char* mpack_expect_utf8_cstr_alloc(mpack_reader_t* reader, size_t maxsize) { size_t length; char* str = mpack_expect_cstr_alloc_unchecked(reader, maxsize, &length); if (str && !mpack_utf8_check_no_null(str, length)) { MPACK_FREE(str); mpack_reader_flag_error(reader, mpack_error_type); return NULL; } return str; }
char* mpack_expect_utf8_alloc(mpack_reader_t* reader, size_t maxsize, size_t* size) { char* str = mpack_expect_str_alloc(reader, maxsize, size); if (str && !mpack_utf8_check(str, *size)) { *size = 0; MPACK_FREE(str); mpack_reader_flag_error(reader, mpack_error_type); return NULL; } return str; }
static void mpack_file_writer_teardown(mpack_writer_t* writer) { FILE* file = (FILE*)writer->context; if (file) { int ret = fclose(file); writer->context = NULL; if (ret != 0) mpack_writer_flag_error(writer, mpack_error_io); } MPACK_FREE(writer->buffer); writer->buffer = NULL; }
static void mpack_file_reader_teardown(mpack_reader_t* reader) { FILE* file = (FILE*)reader->context; if (file) { int ret = fclose(file); reader->context = NULL; if (ret != 0) mpack_reader_flag_error(reader, mpack_error_io); } MPACK_FREE(reader->buffer); reader->buffer = NULL; reader->size = 0; reader->fill = NULL; }
void mpack_writer_init_file(mpack_writer_t* writer, const char* filename) { mpack_assert(filename != NULL, "filename is NULL"); size_t capacity = MPACK_BUFFER_SIZE; char* buffer = (char*)MPACK_MALLOC(capacity); if (buffer == NULL) { mpack_writer_init_error(writer, mpack_error_memory); return; } FILE* file = fopen(filename, "wb"); if (file == NULL) { MPACK_FREE(buffer); mpack_writer_init_error(writer, mpack_error_io); return; } mpack_writer_init(writer, buffer, capacity); mpack_writer_set_context(writer, file); mpack_writer_set_flush(writer, mpack_file_writer_flush); mpack_writer_set_teardown(writer, mpack_file_writer_teardown); }