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) { *out_count = 0; uint32_t count; bool has_array = true; if (allow_nil) has_array = mpack_expect_array_max_or_nil(reader, max_count, &count); else count = mpack_expect_array_max(reader, max_count); if (mpack_reader_error(reader)) return NULL; // size 0 is not an error; we return NULL for no elements. if (count == 0) { // we call mpack_done_array() automatically ONLY if we are using // the _or_nil variant. this is the only way to allow nil and empty // to work the same way. if (allow_nil && has_array) mpack_done_array(reader); return NULL; } void* p = MPACK_MALLOC(element_size * count); if (p == NULL) { mpack_reader_flag_error(reader, mpack_error_memory); return NULL; } *out_count = count; return p; }
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); }
void mpack_writer_init_growable(mpack_writer_t* writer, char** target_data, size_t* target_size) { mpack_assert(target_data != NULL, "cannot initialize writer without a destination for the data"); mpack_assert(target_size != NULL, "cannot initialize writer without a destination for the size"); *target_data = NULL; *target_size = 0; MPACK_STATIC_ASSERT(sizeof(mpack_growable_writer_t) <= sizeof(writer->reserved), "not enough reserved space for growable writer!"); mpack_growable_writer_t* growable_writer = (mpack_growable_writer_t*)mpack_writer_get_reserved(writer); growable_writer->target_data = target_data; growable_writer->target_size = target_size; size_t capacity = MPACK_BUFFER_SIZE; char* buffer = (char*)MPACK_MALLOC(capacity); if (buffer == NULL) { mpack_writer_init_error(writer, mpack_error_memory); return; } mpack_writer_init(writer, buffer, capacity); mpack_writer_set_context(writer, growable_writer); mpack_writer_set_flush(writer, mpack_growable_writer_flush); mpack_writer_set_teardown(writer, mpack_growable_writer_teardown); }
mpack_error_t mpack_track_init(mpack_track_t* track) { track->count = 0; track->capacity = MPACK_TRACKING_INITIAL_CAPACITY; track->elements = (mpack_track_element_t*)MPACK_MALLOC(sizeof(mpack_track_element_t) * track->capacity); if (track->elements == NULL) return mpack_error_memory; return mpack_ok; }
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; }
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); }