Skip to content

v_2_0_cpp_x3_parse

Takatoshi Kondo edited this page Jan 9, 2017 · 4 revisions

Iterator based parser/unpacker using Spirit.X3 (experimental)

What is this?

It is a new parser using Boost.Spirit.X3(experimental). Boost.Spirit.X3 is experimental feature, so the iterator based parser/unpacker is also an experimental feature.

Here is the parser code.

See https://github.com/redboltz/msgpack-c/blob/x3_parse/include/msgpack/v2/x3_parse.hpp

It is quite small. It is completely separete from existing parser/unpacker. The existing parser/unpacker takes the pointer and the size of buffer, but iterator based unpacker/parser takes begin/end iterator pair.

How to use?

Define MSGPACK_USE_X3_PARSE before including msgpack.hpp. It is usually defined via a compiler option such as -DMSGPACK_USE_X3_PARSE.

Requirements

  • Boost 1.61.0 or later
  • C++14 support.

APIs

parse

template <typename Iterator, typename Visitor>
inline bool parse(Iterator&& begin, Iterator&& end, Visitor&& vis);

Visitor need to satisfy visitor concept. If begin is non-const lvalue, then it will be updated after successfully parsed.

See an example.

unpack

template <typename Iterator>
msgpack::object_handle unpack(
    Iterator&& begin, Iterator&& end,
    bool& referenced,
    unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR,
    unpack_limit const& limit = unpack_limit());

template <typename Iterator>
msgpack::object_handle unpack(
    Iterator&& begin, Iterator&& end,
    unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR,
    unpack_limit const& limit = unpack_limit());

template <typename Iterator>
msgpack::object unpack(
    msgpack::zone& z,
    Iterator&& begin, Iterator&& end,
    bool& referenced,
    unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR,
    unpack_limit const& limit = unpack_limit());

template <typename Iterator>
msgpack::object unpack(
    msgpack::zone& z,
    Iterator&& begin, Iterator&& end,
    unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR,
    unpack_limit const& limit = unpack_limit());

They are similar to https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_unpacker#client-controls-a-buffer. The APIs take a pair of iterators instead of data and len.

See an example.

Stream parse/unpack

The iterator based parse/unpack function can be used for stream parsing/unpacking. See https://github.com/redboltz/msgpack-c/blob/x3_parse/example/x3/stream_unpack.cpp.

The client connects to the server. And then sends msgpack formatted data 5bytes each sending. The server unpacks the data.

Here is the unpacking code: https://github.com/redboltz/msgpack-c/blob/x3_parse/example/x3/stream_unpack.cpp#L113

                // use buffered_iterator here
                // b is incremented in msgpack::unpack() and fetch data from sink
                // via coroutine2 mechanism
                auto b = boost::spirit::make_default_multi_pass(buffered_iterator(source));
                auto e = boost::spirit::make_default_multi_pass(buffered_iterator());

                // This is usually an infinity look, but for test, loop is finished when
                // two message pack data is processed.
                for (int i = 0; i != 2; ++i) {
                    auto oh = msgpack::unpack(b, e);
                    std::cout << oh.get() << std::endl;
                }

b is the data source. The type of b is buffered_iterator. It is defined https://github.com/redboltz/msgpack-c/blob/x3_parse/example/x3/stream_unpack.cpp#L34. The iterator contains pull_type of the Boost.Coroutine2. The data type of pull/push is std::shared_ptr<std::vector<char>>. The data is pushed at https://github.com/redboltz/msgpack-c/blob/x3_parse/example/x3/stream_unpack.cpp#L142.

If b spent all data, then pull the next data from the source. That means do_read() and unpack() contexts switch back and forth.