MPack 1.1.1
A C encoding/decoding library for the MessagePack serialization format.
|
The MPack Reader API contains functions for imperatively reading dynamically typed data from a MessagePack stream.
See Using the Reader API for examples.
This forms the basis of the Expect API, which can be used to interpret the stream of elements in expected types and value ranges.
Macros | |
#define | MPACK_READER_MINIMUM_BUFFER_SIZE 32 |
The minimum buffer size for a reader with a fill function. More... | |
Typedefs | |
typedef void(* | mpack_reader_error_t) (mpack_reader_t *reader, mpack_error_t error) |
An error handler function to be called when an error is flagged on the reader. More... | |
typedef size_t(* | mpack_reader_fill_t) (mpack_reader_t *reader, char *buffer, size_t count) |
The MPack reader's fill function. More... | |
typedef void(* | mpack_reader_skip_t) (mpack_reader_t *reader, size_t count) |
The MPack reader's skip function. More... | |
typedef struct mpack_reader_t | mpack_reader_t |
A buffered MessagePack decoder. More... | |
typedef void(* | mpack_reader_teardown_t) (mpack_reader_t *reader) |
A teardown function to be called when the reader is destroyed. More... | |
Lifecycle Functions | |
void | mpack_reader_init (mpack_reader_t *reader, char *buffer, size_t size, size_t count) |
Initializes an MPack reader with the given buffer. More... | |
void | mpack_reader_init_error (mpack_reader_t *reader, mpack_error_t error) |
Initializes an MPack reader directly into an error state. More... | |
void | mpack_reader_init_data (mpack_reader_t *reader, const char *data, size_t count) |
Initializes an MPack reader to parse a pre-loaded contiguous chunk of data. More... | |
void | mpack_reader_init_filename (mpack_reader_t *reader, const char *filename) |
Initializes an MPack reader that reads from a file. More... | |
void | mpack_reader_init_file (mpack_reader_t *reader, const char *filename) |
Deprecated. More... | |
void | mpack_reader_init_stdfile (mpack_reader_t *reader, FILE *stdfile, bool close_when_done) |
Initializes an MPack reader that reads from a libc FILE. More... | |
mpack_error_t | mpack_reader_destroy (mpack_reader_t *reader) |
Cleans up the MPack reader, ensuring that all compound elements have been completely read. More... | |
#define | mpack_reader_init_stack(reader) |
Initializes an MPack reader using stack space as a buffer. More... | |
Callbacks | |
void | mpack_reader_set_context (mpack_reader_t *reader, void *context) |
Sets the custom pointer to pass to the reader callbacks, such as fill or teardown. More... | |
void * | mpack_reader_context (mpack_reader_t *reader) |
Returns the custom context for reader callbacks. More... | |
void | mpack_reader_set_fill (mpack_reader_t *reader, mpack_reader_fill_t fill) |
Sets the fill function to refill the data buffer when it runs out of data. More... | |
void | mpack_reader_set_skip (mpack_reader_t *reader, mpack_reader_skip_t skip) |
Sets the skip function to discard bytes from the source stream. More... | |
void | mpack_reader_set_error_handler (mpack_reader_t *reader, mpack_reader_error_t error_fn) |
Sets the error function to call when an error is flagged on the reader. More... | |
void | mpack_reader_set_teardown (mpack_reader_t *reader, mpack_reader_teardown_t teardown) |
Sets the teardown function to call when the reader is destroyed. More... | |
Core Reader Functions | |
mpack_error_t | mpack_reader_error (mpack_reader_t *reader) |
Queries the error state of the MPack reader. More... | |
void | mpack_reader_flag_error (mpack_reader_t *reader, mpack_error_t error) |
Places the reader in the given error state, calling the error callback if one is set. More... | |
mpack_error_t | mpack_reader_flag_if_error (mpack_reader_t *reader, mpack_error_t error) |
Places the reader in the given error state if the given error is not mpack_ok, returning the resulting error state of the reader. More... | |
size_t | mpack_reader_remaining (mpack_reader_t *reader, const char **data) |
Returns bytes left in the reader's buffer. More... | |
mpack_tag_t | mpack_read_tag (mpack_reader_t *reader) |
Reads a MessagePack object header (an MPack tag.) More... | |
mpack_tag_t | mpack_peek_tag (mpack_reader_t *reader) |
Parses the next MessagePack object header (an MPack tag) without advancing the reader. More... | |
void | mpack_done_type (mpack_reader_t *reader, mpack_type_t type) |
Finishes reading the given type. More... | |
void | mpack_done_array (mpack_reader_t *reader) |
Finishes reading an array. More... | |
void | mpack_done_map (mpack_reader_t *reader) |
Finishes reading a map. More... | |
void | mpack_done_str (mpack_reader_t *reader) |
Finishes reading a string. More... | |
void | mpack_done_bin (mpack_reader_t *reader) |
Finishes reading a binary data blob. More... | |
void | mpack_done_ext (mpack_reader_t *reader) |
Finishes reading an extended type binary data blob. More... | |
void | mpack_discard (mpack_reader_t *reader) |
Reads and discards the next object. More... | |
String and Data Functions | |
void | mpack_skip_bytes (mpack_reader_t *reader, size_t count) |
Skips bytes from the underlying stream. More... | |
void | mpack_read_bytes (mpack_reader_t *reader, char *p, size_t count) |
Reads bytes from a string, binary blob or extension object, copying them into the given buffer. More... | |
void | mpack_read_utf8 (mpack_reader_t *reader, char *p, size_t byte_count) |
Reads bytes from a string, ensures that the string is valid UTF-8, and copies the bytes into the given buffer. More... | |
void | mpack_read_cstr (mpack_reader_t *reader, char *buf, size_t buffer_size, size_t byte_count) |
Reads bytes from a string, ensures that the string contains no NUL bytes, copies the bytes into the given buffer and adds a null-terminator. More... | |
void | mpack_read_utf8_cstr (mpack_reader_t *reader, char *buf, size_t buffer_size, size_t byte_count) |
Reads bytes from a string, ensures that the string is valid UTF-8 with no NUL bytes, copies the bytes into the given buffer and adds a null-terminator. More... | |
char * | mpack_read_bytes_alloc (mpack_reader_t *reader, size_t count) |
Reads bytes from a string, binary blob or extension object, allocating storage for them and returning the allocated pointer. More... | |
const char * | mpack_read_bytes_inplace (mpack_reader_t *reader, size_t count) |
Reads bytes from a string, binary blob or extension object in-place in the buffer. More... | |
const char * | mpack_read_utf8_inplace (mpack_reader_t *reader, size_t count) |
Reads bytes from a string in-place in the buffer and ensures they are valid UTF-8. More... | |
bool | mpack_should_read_bytes_inplace (mpack_reader_t *reader, size_t count) |
Returns true if it's a good idea to read the given number of bytes in-place. More... | |
mpack_timestamp_t | mpack_read_timestamp (mpack_reader_t *reader, size_t size) |
Reads a timestamp contained in an ext object of the given size, closing the ext type. More... | |
#define mpack_reader_init_stack | ( | reader | ) |
Initializes an MPack reader using stack space as a buffer.
A fill function should be added to the reader to fill the buffer.
#define MPACK_READER_MINIMUM_BUFFER_SIZE 32 |
The minimum buffer size for a reader with a fill function.
typedef void(* mpack_reader_error_t) (mpack_reader_t *reader, mpack_error_t error) |
An error handler function to be called when an error is flagged on the reader.
The error handler will only be called once on the first error flagged; any subsequent reads and errors are ignored, and the reader is permanently in that error state.
MPack is safe against non-local jumps out of error handler callbacks. This means you are allowed to longjmp or throw an exception (in C++, Objective-C, or with SEH) out of this callback.
Bear in mind when using longjmp that local non-volatile variables that have changed are undefined when setjmp() returns, so you can't put the reader on the stack in the same activation frame as the setjmp without declaring it volatile.
You must still eventually destroy the reader. It is not destroyed automatically when an error is flagged. It is safe to destroy the reader within this error callback, but you will either need to perform a non-local jump, or store something in your context to identify that the reader is destroyed since any future accesses to it cause undefined behavior.
typedef size_t(* mpack_reader_fill_t) (mpack_reader_t *reader, char *buffer, size_t count) |
The MPack reader's fill function.
It should fill the buffer with at least one byte and at most the given count
, returning the number of bytes written to the buffer.
In case of error, it should flag an appropriate error on the reader (usually mpack_error_io), or simply return zero. If zero is returned, mpack_error_io is raised.
typedef void(* mpack_reader_skip_t) (mpack_reader_t *reader, size_t count) |
The MPack reader's skip function.
It should discard the given number of bytes from the source (for example by seeking forward.)
In case of error, it should flag an appropriate error on the reader.
typedef struct mpack_reader_t mpack_reader_t |
A buffered MessagePack decoder.
The decoder wraps an existing buffer and, optionally, a fill function. This allows efficiently decoding data from existing memory buffers, files, streams, etc.
All read operations are synchronous; they will block until the requested data is fully read, or an error occurs.
This structure is opaque; its fields should not be accessed outside of MPack.
typedef void(* mpack_reader_teardown_t) (mpack_reader_t *reader) |
A teardown function to be called when the reader is destroyed.
void mpack_discard | ( | mpack_reader_t * | reader | ) |
Reads and discards the next object.
This will read and discard all contained data as well if it is a compound type.
void mpack_done_array | ( | mpack_reader_t * | reader | ) |
Finishes reading an array.
This will track reads to ensure that the correct number of elements are read.
mpack_done_bin | ( | mpack_reader_t * | reader | ) |
Finishes reading a binary data blob.
This will track reads to ensure that the correct number of bytes are read.
mpack_done_ext | ( | mpack_reader_t * | reader | ) |
Finishes reading an extended type binary data blob.
This will track reads to ensure that the correct number of bytes are read.
mpack_done_map | ( | mpack_reader_t * | reader | ) |
Finishes reading a map.
This will track reads to ensure that the correct number of elements are read.
mpack_done_str | ( | mpack_reader_t * | reader | ) |
Finishes reading a string.
This will track reads to ensure that the correct number of bytes are read.
void mpack_done_type | ( | mpack_reader_t * | reader, |
mpack_type_t | type | ||
) |
Finishes reading the given type.
This will track reads to ensure that the correct number of elements or bytes are read.
mpack_tag_t mpack_peek_tag | ( | mpack_reader_t * | reader | ) |
Parses the next MessagePack object header (an MPack tag) without advancing the reader.
If an error occurs, the reader is placed in an error state and a nil tag is returned. If the reader is already in an error state, a nil tag is returned.
void mpack_read_bytes | ( | mpack_reader_t * | reader, |
char * | p, | ||
size_t | count | ||
) |
Reads bytes from a string, binary blob or extension object, copying them into the given buffer.
A str, bin or ext must have been opened by a call to mpack_read_tag() which yielded one of these types, or by a call to an expect function such as mpack_expect_str() or mpack_expect_bin().
If an error occurs, the buffer contents are undefined.
This can be called multiple times for a single str, bin or ext to read the data in chunks. The total data read must add up to the size of the object.
reader | The MPack reader |
p | The buffer in which to copy the bytes |
count | The number of bytes to read |
char * mpack_read_bytes_alloc | ( | mpack_reader_t * | reader, |
size_t | count | ||
) |
Reads bytes from a string, binary blob or extension object, allocating storage for them and returning the allocated pointer.
The allocated string must be freed with MPACK_FREE() (or simply free() if MPack's allocator hasn't been customized.)
Returns NULL if any error occurs, or if count is zero.
const char * mpack_read_bytes_inplace | ( | mpack_reader_t * | reader, |
size_t | count | ||
) |
Reads bytes from a string, binary blob or extension object in-place in the buffer.
This can be used to avoid copying the data.
A str, bin or ext must have been opened by a call to mpack_read_tag() which yielded one of these types, or by a call to an expect function such as mpack_expect_str() or mpack_expect_bin().
If the bytes are from a string, the string is not null-terminated! Use mpack_read_cstr() to copy the string into a buffer and add a null-terminator.
The returned pointer is invalidated on the next read, or when the buffer is destroyed.
The reader will move data around in the buffer if needed to ensure that the pointer can always be returned, so this should only be used if count is very small compared to the buffer size. If you need to check whether a small size is reasonable (for example you intend to handle small and large sizes differently), you can call mpack_should_read_bytes_inplace().
This can be called multiple times for a single str, bin or ext to read the data in chunks. The total data read must add up to the size of the object.
NULL is returned if the reader is in an error state.
mpack_error_too_big | if the requested size is larger than the buffer size |
void mpack_read_cstr | ( | mpack_reader_t * | reader, |
char * | buf, | ||
size_t | buffer_size, | ||
size_t | byte_count | ||
) |
Reads bytes from a string, ensures that the string contains no NUL bytes, copies the bytes into the given buffer and adds a null-terminator.
A string must have been opened by a call to mpack_read_tag() which yielded a string, or by a call to an expect function such as mpack_expect_str().
The given byte count must match the size of the string as returned by the tag or expect function. The string will only be copied if the buffer is large enough to store it.
If an error occurs, the buffer will contain an empty string.
mpack_error_too_big | if the string plus null-terminator is larger than the given buffer size |
mpack_error_type | if the string contains a null byte. |
mpack_tag_t mpack_read_tag | ( | mpack_reader_t * | reader | ) |
Reads a MessagePack object header (an MPack tag.)
If an error occurs, the reader is placed in an error state and a nil tag is returned. If the reader is already in an error state, a nil tag is returned.
If the type is compound (i.e. is a map, array, string, binary or extension type), additional reads are required to get the contained data, and the corresponding done function must be called when done.
mpack_timestamp_t mpack_read_timestamp | ( | mpack_reader_t * | reader, |
size_t | size | ||
) |
Reads a timestamp contained in an ext object of the given size, closing the ext type.
An ext object of exttype MPACK_EXTTYPE_TIMESTAMP must have been opened by a call to e.g. mpack_read_tag() or mpack_expect_ext().
You must NOT call mpack_done_ext() after calling this. A timestamp ext object can only contain a single timestamp value, so this calls mpack_done_ext() automatically.
mpack_error_invalid | if the size is not one of the supported timestamp sizes, or if the nanoseconds are out of range. |
void mpack_read_utf8 | ( | mpack_reader_t * | reader, |
char * | p, | ||
size_t | byte_count | ||
) |
Reads bytes from a string, ensures that the string is valid UTF-8, and copies the bytes into the given buffer.
A string must have been opened by a call to mpack_read_tag() which yielded a string, or by a call to an expect function such as mpack_expect_str().
The given byte count must match the complete size of the string as returned by the tag or expect function. You must ensure that the buffer fits the data.
This does not accept any UTF-8 variant such as Modified UTF-8, CESU-8 or WTF-8. Only pure UTF-8 is allowed.
If an error occurs, the buffer contents are undefined.
Unlike mpack_read_bytes(), this cannot be used to read the data in chunks (since this might split a character's UTF-8 bytes, and the reader does not keep track of the UTF-8 decoding state between reads.)
mpack_error_type | if the string contains invalid UTF-8. |
void mpack_read_utf8_cstr | ( | mpack_reader_t * | reader, |
char * | buf, | ||
size_t | buffer_size, | ||
size_t | byte_count | ||
) |
Reads bytes from a string, ensures that the string is valid UTF-8 with no NUL bytes, copies the bytes into the given buffer and adds a null-terminator.
A string must have been opened by a call to mpack_read_tag() which yielded a string, or by a call to an expect function such as mpack_expect_str().
The given byte count must match the size of the string as returned by the tag or expect function. The string will only be copied if the buffer is large enough to store it.
This does not accept any UTF-8 variant such as Modified UTF-8, CESU-8 or WTF-8. Only pure UTF-8 is allowed, but without the NUL character, since it cannot be represented in a null-terminated string.
If an error occurs, the buffer will contain an empty string.
mpack_error_too_big | if the string plus null-terminator is larger than the given buffer size |
mpack_error_type | if the string contains invalid UTF-8 or a null byte. |
const char * mpack_read_utf8_inplace | ( | mpack_reader_t * | reader, |
size_t | count | ||
) |
Reads bytes from a string in-place in the buffer and ensures they are valid UTF-8.
This can be used to avoid copying the data.
A string must have been opened by a call to mpack_read_tag() which yielded a string, or by a call to an expect function such as mpack_expect_str().
The string is not null-terminated! Use mpack_read_utf8_cstr() to copy the string into a buffer and add a null-terminator.
The returned pointer is invalidated on the next read, or when the buffer is destroyed.
The reader will move data around in the buffer if needed to ensure that the pointer can always be returned, so this should only be used if count is very small compared to the buffer size. If you need to check whether a small size is reasonable (for example you intend to handle small and large sizes differently), you can call mpack_should_read_bytes_inplace().
This does not accept any UTF-8 variant such as Modified UTF-8, CESU-8 or WTF-8. Only pure UTF-8 is allowed.
Unlike mpack_read_bytes_inplace(), this cannot be used to read the data in chunks (since this might split a character's UTF-8 bytes, and the reader does not keep track of the UTF-8 decoding state between reads.)
NULL is returned if the reader is in an error state.
mpack_error_type | if the string contains invalid UTF-8 |
mpack_error_too_big | if the requested size is larger than the buffer size |
void * mpack_reader_context | ( | mpack_reader_t * | reader | ) |
Returns the custom context for reader callbacks.
mpack_error_t mpack_reader_destroy | ( | mpack_reader_t * | reader | ) |
Cleans up the MPack reader, ensuring that all compound elements have been completely read.
Returns the final error state of the reader.
This will assert in tracking mode if the reader is not in an error state and has any incomplete reads. If you want to cancel reading in the middle of a document, you need to flag an error on the reader before destroying it (such as mpack_error_data).
mpack_error_t mpack_reader_error | ( | mpack_reader_t * | reader | ) |
Queries the error state of the MPack reader.
If a reader is in an error state, you should discard all data since the last time the error flag was checked. The error flag cannot be cleared.
void mpack_reader_flag_error | ( | mpack_reader_t * | reader, |
mpack_error_t | error | ||
) |
Places the reader in the given error state, calling the error callback if one is set.
This allows you to externally flag errors, for example if you are validating data as you read it.
If the reader is already in an error state, this call is ignored and no error callback is called.
mpack_error_t mpack_reader_flag_if_error | ( | mpack_reader_t * | reader, |
mpack_error_t | error | ||
) |
Places the reader in the given error state if the given error is not mpack_ok, returning the resulting error state of the reader.
This allows you to externally flag errors, for example if you are validating data as you read it.
If the given error is mpack_ok or if the reader is already in an error state, this call is ignored and the actual error state of the reader is returned.
void mpack_reader_init | ( | mpack_reader_t * | reader, |
char * | buffer, | ||
size_t | size, | ||
size_t | count | ||
) |
Initializes an MPack reader with the given buffer.
The reader does not assume ownership of the buffer, but the buffer must be writeable if a fill function will be used to refill it.
reader | The MPack reader. |
buffer | The buffer with which to read MessagePack data. |
size | The size of the buffer. |
count | The number of bytes already in the buffer. |
void mpack_reader_init_data | ( | mpack_reader_t * | reader, |
const char * | data, | ||
size_t | count | ||
) |
Initializes an MPack reader to parse a pre-loaded contiguous chunk of data.
The reader does not assume ownership of the data.
reader | The MPack reader. |
data | The data to parse. |
count | The number of bytes pointed to by data. |
void mpack_reader_init_error | ( | mpack_reader_t * | reader, |
mpack_error_t | error | ||
) |
Initializes an MPack reader directly into an error state.
Use this if you are writing a wrapper to mpack_reader_init() which can fail its setup.
void mpack_reader_init_file | ( | mpack_reader_t * | reader, |
const char * | filename | ||
) |
Deprecated.
void mpack_reader_init_filename | ( | mpack_reader_t * | reader, |
const char * | filename | ||
) |
Initializes an MPack reader that reads from a file.
The file will be automatically opened and closed by the reader.
void mpack_reader_init_stdfile | ( | mpack_reader_t * | reader, |
FILE * | stdfile, | ||
bool | close_when_done | ||
) |
Initializes an MPack reader that reads from a libc FILE.
This can be used to read from stdin, or from a file opened separately.
reader | The MPack reader. |
stdfile | The FILE. |
close_when_done | If true, fclose() will be called on the FILE when it is no longer needed. If false, the file will not be closed when reading is done. |
size_t mpack_reader_remaining | ( | mpack_reader_t * | reader, |
const char ** | data | ||
) |
Returns bytes left in the reader's buffer.
If you are done reading MessagePack data but there is other interesting data following it, the reader may have buffered too much data. The number of bytes remaining in the buffer and a pointer to the position of those bytes can be queried here.
If you know the length of the MPack chunk beforehand, it's better to instead have your fill function limit the data it reads so that the reader does not have extra data. In this case you can simply check that this returns zero.
Returns 0 if the reader is in an error state.
reader | The MPack reader from which to query remaining data. |
data | [out] A pointer to the remaining data, or NULL. |
void mpack_reader_set_context | ( | mpack_reader_t * | reader, |
void * | context | ||
) |
Sets the custom pointer to pass to the reader callbacks, such as fill or teardown.
reader | The MPack reader. |
context | User data to pass to the reader callbacks. |
void mpack_reader_set_error_handler | ( | mpack_reader_t * | reader, |
mpack_reader_error_t | error_fn | ||
) |
Sets the error function to call when an error is flagged on the reader.
This should normally be used with mpack_reader_set_context() to register a custom pointer to pass to the error function.
See the definition of mpack_reader_error_t for more information about what you can do from an error callback.
reader | The MPack reader. |
error_fn | The function to call when an error is flagged on the reader. |
void mpack_reader_set_fill | ( | mpack_reader_t * | reader, |
mpack_reader_fill_t | fill | ||
) |
Sets the fill function to refill the data buffer when it runs out of data.
If no fill function is used, truncated MessagePack data results in mpack_error_invalid (since the buffer is assumed to contain a complete MessagePack object.)
If a fill function is used, truncated MessagePack data usually results in mpack_error_io (since the fill function fails to get the missing data.)
This should normally be used with mpack_reader_set_context() to register a custom pointer to pass to the fill function.
reader | The MPack reader. |
fill | The function to fetch additional data into the buffer. |
void mpack_reader_set_skip | ( | mpack_reader_t * | reader, |
mpack_reader_skip_t | skip | ||
) |
Sets the skip function to discard bytes from the source stream.
It's not necessary to implement this function. If the stream is not seekable, don't set a skip callback. The reader will fall back to using the fill function instead.
This should normally be used with mpack_reader_set_context() to register a custom pointer to pass to the skip function.
The skip function is ignored in size-optimized builds to reduce code size. Data will be skipped with the fill function when necessary.
reader | The MPack reader. |
skip | The function to discard bytes from the source stream. |
void mpack_reader_set_teardown | ( | mpack_reader_t * | reader, |
mpack_reader_teardown_t | teardown | ||
) |
Sets the teardown function to call when the reader is destroyed.
This should normally be used with mpack_reader_set_context() to register a custom pointer to pass to the teardown function.
reader | The MPack reader. |
teardown | The function to call when the reader is destroyed. |
bool mpack_should_read_bytes_inplace | ( | mpack_reader_t * | reader, |
size_t | count | ||
) |
Returns true if it's a good idea to read the given number of bytes in-place.
If the read will be larger than some small fraction of the buffer size, this will return false to avoid shuffling too much data back and forth in the buffer.
Use this if you're expecting arbitrary size data, and you want to read in-place for the best performance when possible but will fall back to a normal read if the data is too large.
void mpack_skip_bytes | ( | mpack_reader_t * | reader, |
size_t | count | ||
) |
Skips bytes from the underlying stream.
This is used only to skip the contents of a string, binary blob or extension object.