void mpack_reader_init_error(mpack_reader_t* reader, mpack_error_t error) { mpack_memset(reader, 0, sizeof(*reader)); reader->error = error; mpack_log("===========================\n"); mpack_log("initializing reader error state %i\n", (int)error); }
void mpack_reader_init(mpack_reader_t* reader, char* buffer, size_t size, size_t count) { mpack_assert(buffer != NULL, "buffer is NULL"); mpack_memset(reader, 0, sizeof(*reader)); reader->buffer = buffer; reader->size = size; reader->left = count; #if MPACK_READ_TRACKING mpack_reader_flag_if_error(reader, mpack_track_init(&reader->track)); #endif mpack_log("===========================\n"); mpack_log("initializing reader with buffer size %i\n", (int)size); }
mpack_tag_t mpack_peek_tag(mpack_reader_t* reader) { mpack_log("peeking tag\n"); // make sure we can peek a tag if (mpack_reader_error(reader) != mpack_ok) return mpack_tag_nil(); if (mpack_reader_track_peek_element(reader) != mpack_ok) return mpack_tag_nil(); mpack_tag_t tag; mpack_memset(&tag, 0, sizeof(tag)); if (mpack_parse_tag(reader, &tag) == 0) return mpack_tag_nil(); return tag; }
static void mpack_writer_clear(mpack_writer_t* writer) { writer->flush = NULL; writer->error_fn = NULL; writer->teardown = NULL; writer->context = NULL; writer->buffer = NULL; writer->size = 0; writer->used = 0; writer->error = mpack_ok; #if MPACK_WRITE_TRACKING mpack_memset(&writer->track, 0, sizeof(writer->track)); #endif }
mpack_tag_t mpack_read_tag(mpack_reader_t* reader) { mpack_log("reading tag\n"); // make sure we can read a tag if (mpack_reader_error(reader) != mpack_ok) return mpack_tag_nil(); if (mpack_reader_track_element(reader) != mpack_ok) return mpack_tag_nil(); mpack_tag_t tag; mpack_memset(&tag, 0, sizeof(tag)); size_t count = mpack_parse_tag(reader, &tag); if (count == 0) return mpack_tag_nil(); #if MPACK_READ_TRACKING mpack_error_t track_error = mpack_ok; switch (tag.type) { case mpack_type_map: case mpack_type_array: track_error = mpack_track_push(&reader->track, tag.type, tag.v.l); break; case mpack_type_str: case mpack_type_bin: case mpack_type_ext: track_error = mpack_track_push(&reader->track, tag.type, tag.v.n); break; default: break; } if (track_error != mpack_ok) { mpack_reader_flag_error(reader, track_error); return mpack_tag_nil(); } #endif // the tag is guaranteed to have been read out of // the buffer, so we advance past it reader->pos += count; reader->left -= count; return tag; }
void mpack_reader_init_data(mpack_reader_t* reader, const char* data, size_t count) { mpack_assert(data != NULL, "data is NULL"); mpack_memset(reader, 0, sizeof(*reader)); reader->left = count; // unfortunately we have to cast away the const to store the buffer, // but we won't be modifying it because there's no fill function. // the buffer size is left at 0 to ensure no fill function can be // set or used (see mpack_reader_set_fill().) #ifdef __cplusplus reader->buffer = const_cast<char*>(data); #else reader->buffer = (char*)data; #endif #if MPACK_READ_TRACKING mpack_reader_flag_if_error(reader, mpack_track_init(&reader->track)); #endif mpack_log("===========================\n"); mpack_log("initializing reader with data size %i\n", (int)count); }
// Reads count bytes into p. Used when there are not enough bytes // left in the buffer to satisfy a read. void mpack_read_native_big(mpack_reader_t* reader, char* p, size_t count) { mpack_assert(count == 0 || p != NULL, "data pointer for %i bytes is NULL", (int)count); if (mpack_reader_error(reader) != mpack_ok) { mpack_memset(p, 0, count); return; } mpack_log("big read for %i bytes into %p, %i left in buffer, buffer size %i\n", (int)count, p, (int)reader->left, (int)reader->size); if (count <= reader->left) { mpack_assert(0, "big read requested for %i bytes, but there are %i bytes " "left in buffer. call mpack_read_native() instead", (int)count, (int)reader->left); mpack_reader_flag_error(reader, mpack_error_bug); mpack_memset(p, 0, count); return; } // we'll need a fill function to get more data. if there's no // fill function, the buffer should contain an entire MessagePack // object, so we raise mpack_error_invalid instead of mpack_error_io // on truncated data. if (reader->fill == NULL) { mpack_reader_flag_error(reader, mpack_error_invalid); mpack_memset(p, 0, count); return; } if (reader->size == 0) { // somewhat debatable what error should be returned here. when // initializing a reader with an in-memory buffer it's not // necessarily a bug if the data is blank; it might just have // been truncated to zero. for this reason we return the same // error as if the data was truncated. mpack_reader_flag_error(reader, mpack_error_io); mpack_memset(p, 0, count); return; } // flush what's left of the buffer if (reader->left > 0) { mpack_log("flushing %i bytes remaining in buffer\n", (int)reader->left); mpack_memcpy(p, reader->buffer + reader->pos, reader->left); count -= reader->left; p += reader->left; reader->pos += reader->left; reader->left = 0; } // we read only in multiples of the buffer size. read the middle portion, if any size_t middle = count - (count % reader->size); if (middle > 0) { mpack_log("reading %i bytes in middle\n", (int)middle); if (mpack_fill(reader, p, middle) < middle) { mpack_reader_flag_error(reader, mpack_error_io); mpack_memset(p, 0, count); return; } count -= middle; p += middle; if (count == 0) return; } // fill the buffer reader->pos = 0; reader->left = mpack_fill(reader, reader->buffer, reader->size); mpack_log("filled %i bytes into buffer\n", (int)reader->left); if (reader->left < count) { mpack_reader_flag_error(reader, mpack_error_io); mpack_memset(p, 0, count); return; } // serve the remainder mpack_log("serving %i remaining bytes from %p to %p\n", (int)count, reader->buffer+reader->pos,p); mpack_memcpy(p, reader->buffer + reader->pos, count); reader->pos += count; reader->left -= count; }