Loading...
Searching...
No Matches
Using the Node API

The Node API is used to parse MessagePack data into a tree in memory, providing DOM-style random access to its contents.

The Node API can parse from a chunk of data in memory, or it can pull data from a file or stream. When the Node API uses a file or stream, it collects the data for a single message into one contiguous buffer in memory as it parses. The nodes for strings and binary data simply point to the data in the buffer, minimizing copies of the data. In this sense, a tree is just an index over a contiguous MessagePack message in memory.

# The Basics

A tree is initialized with one of the `init()` functions, and optionally configured (e.g. with `mpack_set_limits()`.) A complete message is then parsed with `mpack_tree_parse()`.

The data can then be accessed in random order. For example:

bool parse_messagepack(const char* data, size_t count) {
mpack_tree_t tree;
mpack_tree_init_data(&tree, data, count);
mpack_tree_parse(&tree);
mpack_node_t root = mpack_tree_root(&tree);
do_something_with_node(root);
return mpack_tree_destroy(&tree) == mpack_ok;
}
mpack_ok
@ mpack_ok
No error.
Definition: mpack-common.h:162
mpack_node_t
struct mpack_node_t mpack_node_t
A handle to node data in a parsed MPack tree.
Definition: mpack-node.h:63
mpack_tree_root
mpack_node_t mpack_tree_root(mpack_tree_t *tree)
Returns the root node of the tree, if the tree is not in an error state.
mpack_tree_init_data
void mpack_tree_init_data(mpack_tree_t *tree, const char *data, size_t length)
Initializes a tree parser with the given data.
mpack_tree_parse
void mpack_tree_parse(mpack_tree_t *tree)
Parses a MessagePack message into a tree of immutable nodes.
mpack_tree_t
struct mpack_tree_t mpack_tree_t
An MPack tree parser to parse a blob or stream of MessagePack.
Definition: mpack-node.h:82
mpack_tree_destroy
mpack_error_t mpack_tree_destroy(mpack_tree_t *tree)
Destroys the tree.

As with the Expect API, the Node API contains helper functions for extracting data of expected types from the tree, and for stepping into maps and arrays. These can be nested together to quickly unpack a message.

For example, to parse the data on the msgpack.org homepage from a node:

void parse_msgpack_homepage(mpack_node_t node, bool* compact, int* schema) {
*compact = mpack_node_bool(mpack_node_map_cstr(root, "compact"));
*schema = mpack_node_int(mpack_node_map_cstr(root, "schema"));
}
mpack_node_map_cstr
mpack_node_t mpack_node_map_cstr(mpack_node_t node, const char *cstr)
Returns the value node in the given map for the given null-terminated string key.
mpack_node_int
int mpack_node_int(mpack_node_t node)
Returns the int value of the node.
mpack_node_bool
bool mpack_node_bool(mpack_node_t node)
Returns the bool value of the node.

If any error occurs, these functions always return safe values and flag an error on the tree. You do not have to check the tree for errors in between each step; you only need an error check before using the data.

# Continuous Streams

The Node API can parse messages indefinitely from a continuous stream. This can be used for inter-process or network communications. See msgpack-rpc for an example networking protocol.

Here's a minimal example that wraps a tree parser around a BSD socket. We've defined a `stream_t` object to contain our file descriptor and other stream state, and we use it as the tree's context.

#define MAX_SIZE (1024*1024)
#define MAX_NODES 1024
typedef struct stream_t {
int fd;
} stream_t;
static size_t read_stream(mpack_tree_t* tree, char* buffer, size_t count) {
stream_t* stream = mpack_tree_context(tree);
ssize_t step = read(stream->fd, buffer, count);
if (step <= 0)
mpack_tree_flag_error(tree, mpack_error_io);
}
void parse_stream(stream_t* stream) {
mpack_tree_t tree;
mpack_tree_init_stream(&tree, &read_stream, stream, MAX_SIZE, MAX_NODES);
while (true) {
mpack_tree_parse(&tree)
if (mpack_tree_error(&tree) != mpack_error_ok))
break;
received_message(mpack_tree_root(&tree));
}
}
mpack_error_io
@ mpack_error_io
The reader or writer failed to fill or flush, or some other file or socket error occurred.
Definition: mpack-common.h:163
mpack_tree_init_stream
void mpack_tree_init_stream(mpack_tree_t *tree, mpack_tree_read_t read_fn, void *context, size_t max_message_size, size_t max_message_nodes)
Initializes a tree parser from an unbounded stream, or a stream of unknown length.
mpack_tree_flag_error
void mpack_tree_flag_error(mpack_tree_t *tree, mpack_error_t error)
Places the tree in the given error state, calling the error callback if one is set.
mpack_tree_context
void * mpack_tree_context(mpack_tree_t *tree)
Returns the custom context for tree callbacks.
Definition: mpack-node.h:549
mpack_tree_error
mpack_error_t mpack_tree_error(mpack_tree_t *tree)
Returns the error state of the tree.
Definition: mpack-node.h:508

The function `received_message()` will be called with each new message received from the peer.

The Node API contains many more features, including non-blocking parsing, optional map lookups and more. This document is a work in progress. See the Node API reference for more information.