mpack_error_t mpack_track_bytes(mpack_track_t* track, bool read, uint64_t count) { MPACK_UNUSED(read); mpack_assert(track->elements, "null track elements!"); if (track->count == 0) { mpack_break("bytes cannot be %s with no open bin, str or ext", read ? "read" : "written"); return mpack_error_bug; } mpack_track_element_t* element = &track->elements[track->count - 1]; if (element->type == mpack_type_map || element->type == mpack_type_array) { mpack_break("bytes cannot be %s within an %s", read ? "read" : "written", mpack_type_to_string(element->type)); return mpack_error_bug; } if (element->left < count) { mpack_break("too many bytes %s for %s", read ? "read" : "written", mpack_type_to_string(element->type)); return mpack_error_bug; } element->left -= count; return mpack_ok; }
mpack_error_t mpack_track_pop(mpack_track_t* track, mpack_type_t type) { mpack_assert(track->elements, "null track elements!"); mpack_log("track popping %s\n", mpack_type_to_string(type)); if (track->count == 0) { mpack_break("attempting to close a %s but nothing was opened!", mpack_type_to_string(type)); return mpack_error_bug; } mpack_track_element_t* element = &track->elements[track->count - 1]; if (element->type != type) { mpack_break("attempting to close a %s but the open element is a %s!", mpack_type_to_string(type), mpack_type_to_string(element->type)); return mpack_error_bug; } if (element->left != 0) { mpack_break("attempting to close a %s but there are %" PRIu64 " %s left", mpack_type_to_string(type), element->left, (type == mpack_type_map || type == mpack_type_array) ? "elements" : "bytes"); return mpack_error_bug; } --track->count; return mpack_ok; }
mpack_error_t mpack_track_check_empty(mpack_track_t* track) { if (track->count != 0) { mpack_break("unclosed %s", mpack_type_to_string(track->elements[0].type)); return mpack_error_bug; } return mpack_ok; }
mpack_error_t mpack_track_str_bytes_all(mpack_track_t* track, bool read, uint64_t count) { mpack_error_t error = mpack_track_bytes(track, read, count); if (error != mpack_ok) return error; mpack_track_element_t* element = &track->elements[track->count - 1]; if (element->type != mpack_type_str) { mpack_break("the open type must be a string, not a %s", mpack_type_to_string(element->type)); return mpack_error_bug; } if (element->left != 0) { mpack_break("not all bytes were read; the wrong byte count was requested for a string read."); return mpack_error_bug; } return mpack_ok; }
void mpack_reader_set_fill(mpack_reader_t* reader, mpack_reader_fill_t fill) { MPACK_STATIC_ASSERT(MPACK_READER_MINIMUM_BUFFER_SIZE >= MPACK_MAXIMUM_TAG_SIZE, "minimum buffer size must fit any tag!"); if (reader->size == 0) { mpack_break("cannot use fill function without a writeable buffer!"); mpack_reader_flag_error(reader, mpack_error_bug); return; } if (reader->size < MPACK_READER_MINIMUM_BUFFER_SIZE) { mpack_break("buffer size is %i, but minimum buffer size for fill is %i", (int)reader->size, MPACK_READER_MINIMUM_BUFFER_SIZE); mpack_reader_flag_error(reader, mpack_error_bug); return; } reader->fill = fill; }
void mpack_writer_set_flush(mpack_writer_t* writer, mpack_writer_flush_t flush) { MPACK_STATIC_ASSERT(MPACK_WRITER_MINIMUM_BUFFER_SIZE >= MPACK_MAXIMUM_TAG_SIZE, "minimum buffer size must fit any tag!"); if (writer->size < MPACK_WRITER_MINIMUM_BUFFER_SIZE) { mpack_break("buffer size is %i, but minimum buffer size for flush is %i", (int)writer->size, MPACK_WRITER_MINIMUM_BUFFER_SIZE); mpack_writer_flag_error(writer, mpack_error_bug); return; } writer->flush = flush; }
mpack_error_t mpack_track_peek_element(mpack_track_t* track, bool read) { MPACK_UNUSED(read); mpack_assert(track->elements, "null track elements!"); // if there are no open elements, that's fine, we can read/write elements at will if (track->count == 0) return mpack_ok; mpack_track_element_t* element = &track->elements[track->count - 1]; if (element->type != mpack_type_map && element->type != mpack_type_array) { mpack_break("elements cannot be %s within an %s", read ? "read" : "written", mpack_type_to_string(element->type)); return mpack_error_bug; } if (element->left == 0) { mpack_break("too many elements %s for %s", read ? "read" : "written", mpack_type_to_string(element->type)); return mpack_error_bug; } return mpack_ok; }
static char* mpack_expect_cstr_alloc_unchecked(mpack_reader_t* reader, size_t maxsize, size_t* out_length) { *out_length = 0; // make sure argument makes sense if (maxsize < 1) { mpack_break("maxsize is zero; you must have room for at least a null-terminator"); mpack_reader_flag_error(reader, mpack_error_bug); return NULL; } if (maxsize > UINT32_MAX) maxsize = UINT32_MAX; size_t length = mpack_expect_str_max(reader, (uint32_t)maxsize - 1); char* str = mpack_read_bytes_alloc_size(reader, length, length + 1); mpack_done_str(reader); if (str) { str[length] = 0; *out_length = length; } return str; }