From 1d055261b4144dbf86b2658437015b15d4dd9bff Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 4 Sep 2022 00:32:56 +0100 Subject: initial --- include/jsoncons_ext/msgpack/decode_msgpack.hpp | 202 ++++++ include/jsoncons_ext/msgpack/encode_msgpack.hpp | 142 +++++ include/jsoncons_ext/msgpack/msgpack.hpp | 24 + include/jsoncons_ext/msgpack/msgpack_cursor.hpp | 343 +++++++++++ include/jsoncons_ext/msgpack/msgpack_cursor2.hpp | 259 ++++++++ include/jsoncons_ext/msgpack/msgpack_encoder.hpp | 753 +++++++++++++++++++++++ include/jsoncons_ext/msgpack/msgpack_error.hpp | 94 +++ include/jsoncons_ext/msgpack/msgpack_options.hpp | 74 +++ include/jsoncons_ext/msgpack/msgpack_parser.hpp | 748 ++++++++++++++++++++++ include/jsoncons_ext/msgpack/msgpack_reader.hpp | 116 ++++ include/jsoncons_ext/msgpack/msgpack_type.hpp | 63 ++ 11 files changed, 2818 insertions(+) create mode 100644 include/jsoncons_ext/msgpack/decode_msgpack.hpp create mode 100644 include/jsoncons_ext/msgpack/encode_msgpack.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_cursor.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_cursor2.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_encoder.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_error.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_options.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_parser.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_reader.hpp create mode 100644 include/jsoncons_ext/msgpack/msgpack_type.hpp (limited to 'include/jsoncons_ext/msgpack') diff --git a/include/jsoncons_ext/msgpack/decode_msgpack.hpp b/include/jsoncons_ext/msgpack/decode_msgpack.hpp new file mode 100644 index 0000000..614af3d --- /dev/null +++ b/include/jsoncons_ext/msgpack/decode_msgpack.hpp @@ -0,0 +1,202 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_DECODE_MSGPACK_HPP +#define JSONCONS_MSGPACK_DECODE_MSGPACK_HPP + +#include +#include +#include +#include // std::enable_if +#include // std::basic_istream +#include +#include +#include +#include +#include + +namespace jsoncons { +namespace msgpack { + + template + typename std::enable_if::value && + type_traits::is_byte_sequence::value,T>::type + decode_msgpack(const Source& v, + const msgpack_decode_options& options = msgpack_decode_options()) + { + jsoncons::json_decoder decoder; + auto adaptor = make_json_visitor_adaptor(decoder); + basic_msgpack_reader reader(v, adaptor, options); + reader.read(); + if (!decoder.is_valid()) + { + JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column())); + } + return decoder.get_result(); + } + + template + typename std::enable_if::value && + type_traits::is_byte_sequence::value,T>::type + decode_msgpack(const Source& v, + const msgpack_decode_options& options = msgpack_decode_options()) + { + basic_msgpack_cursor cursor(v, options); + json_decoder> decoder{}; + + std::error_code ec; + T val = decode_traits::decode(cursor, decoder, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column())); + } + return val; + } + + template + typename std::enable_if::value,T>::type + decode_msgpack(std::istream& is, + const msgpack_decode_options& options = msgpack_decode_options()) + { + jsoncons::json_decoder decoder; + auto adaptor = make_json_visitor_adaptor(decoder); + msgpack_stream_reader reader(is, adaptor, options); + reader.read(); + if (!decoder.is_valid()) + { + JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column())); + } + return decoder.get_result(); + } + + template + typename std::enable_if::value,T>::type + decode_msgpack(std::istream& is, + const msgpack_decode_options& options = msgpack_decode_options()) + { + basic_msgpack_cursor cursor(is, options); + json_decoder> decoder{}; + + std::error_code ec; + T val = decode_traits::decode(cursor, decoder, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column())); + } + return val; + } + + template + typename std::enable_if::value,T>::type + decode_msgpack(InputIt first, InputIt last, + const msgpack_decode_options& options = msgpack_decode_options()) + { + jsoncons::json_decoder decoder; + auto adaptor = make_json_visitor_adaptor(decoder); + basic_msgpack_reader> reader(binary_iterator_source(first, last), adaptor, options); + reader.read(); + if (!decoder.is_valid()) + { + JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column())); + } + return decoder.get_result(); + } + + template + typename std::enable_if::value,T>::type + decode_msgpack(InputIt first, InputIt last, + const msgpack_decode_options& options = msgpack_decode_options()) + { + basic_msgpack_cursor> cursor(binary_iterator_source(first, last), options); + json_decoder> decoder{}; + + std::error_code ec; + T val = decode_traits::decode(cursor, decoder, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column())); + } + return val; + } + + // With leading allocator parameter + + template + typename std::enable_if::value && + type_traits::is_byte_sequence::value,T>::type + decode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, + const Source& v, + const msgpack_decode_options& options = msgpack_decode_options()) + { + json_decoder decoder(temp_alloc); + auto adaptor = make_json_visitor_adaptor(decoder); + basic_msgpack_reader reader(v, adaptor, options, temp_alloc); + reader.read(); + if (!decoder.is_valid()) + { + JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column())); + } + return decoder.get_result(); + } + + template + typename std::enable_if::value && + type_traits::is_byte_sequence::value,T>::type + decode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, + const Source& v, + const msgpack_decode_options& options = msgpack_decode_options()) + { + basic_msgpack_cursor cursor(v, options, temp_alloc); + json_decoder,TempAllocator> decoder(temp_alloc, temp_alloc); + + std::error_code ec; + T val = decode_traits::decode(cursor, decoder, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column())); + } + return val; + } + + template + typename std::enable_if::value,T>::type + decode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, + std::istream& is, + const msgpack_decode_options& options = msgpack_decode_options()) + { + json_decoder decoder(temp_alloc); + auto adaptor = make_json_visitor_adaptor(decoder); + basic_msgpack_reader reader(is, adaptor, options, temp_alloc); + reader.read(); + if (!decoder.is_valid()) + { + JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column())); + } + return decoder.get_result(); + } + + template + typename std::enable_if::value,T>::type + decode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, + std::istream& is, + const msgpack_decode_options& options = msgpack_decode_options()) + { + basic_msgpack_cursor cursor(is, options, temp_alloc); + json_decoder,TempAllocator> decoder(temp_alloc, temp_alloc); + + std::error_code ec; + T val = decode_traits::decode(cursor, decoder, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column())); + } + return val; + } + +} // msgpack +} // jsoncons + +#endif diff --git a/include/jsoncons_ext/msgpack/encode_msgpack.hpp b/include/jsoncons_ext/msgpack/encode_msgpack.hpp new file mode 100644 index 0000000..10a61e0 --- /dev/null +++ b/include/jsoncons_ext/msgpack/encode_msgpack.hpp @@ -0,0 +1,142 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_ENCODE_MSGPACK_HPP +#define JSONCONS_MSGPACK_ENCODE_MSGPACK_HPP + +#include +#include +#include +#include // std::enable_if +#include // std::basic_istream +#include +#include +#include +#include + +namespace jsoncons { +namespace msgpack { + + template + typename std::enable_if::value && + type_traits::is_back_insertable_byte_container::value,void>::type + encode_msgpack(const T& j, + Container& v, + const msgpack_encode_options& options = msgpack_encode_options()) + { + using char_type = typename T::char_type; + basic_msgpack_encoder> encoder(v, options); + auto adaptor = make_json_visitor_adaptor>(encoder); + j.dump(adaptor); + } + + template + typename std::enable_if::value && + type_traits::is_back_insertable_byte_container::value,void>::type + encode_msgpack(const T& val, + Container& v, + const msgpack_encode_options& options = msgpack_encode_options()) + { + basic_msgpack_encoder> encoder(v, options); + std::error_code ec; + encode_traits::encode(val, encoder, json(), ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + template + typename std::enable_if::value,void>::type + encode_msgpack(const T& j, + std::ostream& os, + const msgpack_encode_options& options = msgpack_encode_options()) + { + using char_type = typename T::char_type; + msgpack_stream_encoder encoder(os, options); + auto adaptor = make_json_visitor_adaptor>(encoder); + j.dump(adaptor); + } + + template + typename std::enable_if::value,void>::type + encode_msgpack(const T& val, + std::ostream& os, + const msgpack_encode_options& options = msgpack_encode_options()) + { + msgpack_stream_encoder encoder(os, options); + std::error_code ec; + encode_traits::encode(val, encoder, json(), ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + // with temp_allocator_arg_t + + template + typename std::enable_if::value && + type_traits::is_back_insertable_byte_container::value,void>::type + encode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, const T& j, + Container& v, + const msgpack_encode_options& options = msgpack_encode_options()) + { + using char_type = typename T::char_type; + basic_msgpack_encoder,TempAllocator> encoder(v, options, temp_alloc); + auto adaptor = make_json_visitor_adaptor>(encoder); + j.dump(adaptor); + } + + template + typename std::enable_if::value && + type_traits::is_back_insertable_byte_container::value,void>::type + encode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, + const T& val, Container& v, + const msgpack_encode_options& options = msgpack_encode_options()) + { + basic_msgpack_encoder,TempAllocator> encoder(v, options, temp_alloc); + std::error_code ec; + encode_traits::encode(val, encoder, json(), ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + template + typename std::enable_if::value,void>::type + encode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, + const T& j, + std::ostream& os, + const msgpack_encode_options& options = msgpack_encode_options()) + { + using char_type = typename T::char_type; + basic_msgpack_encoder encoder(os, options, temp_alloc); + auto adaptor = make_json_visitor_adaptor>(encoder); + j.dump(adaptor); + } + + template + typename std::enable_if::value,void>::type + encode_msgpack(temp_allocator_arg_t, const TempAllocator& temp_alloc, + const T& val, + std::ostream& os, + const msgpack_encode_options& options = msgpack_encode_options()) + { + basic_msgpack_encoder encoder(os, options, temp_alloc); + std::error_code ec; + encode_traits::encode(val, encoder, json(), ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + +} // msgpack +} // jsoncons + +#endif diff --git a/include/jsoncons_ext/msgpack/msgpack.hpp b/include/jsoncons_ext/msgpack/msgpack.hpp new file mode 100644 index 0000000..307aad2 --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack.hpp @@ -0,0 +1,24 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_HPP +#define JSONCONS_MSGPACK_MSGPACK_HPP + +#include +#include +#include +#include // std::enable_if +#include // std::basic_istream +#include +#include +#include +#include +#include +#include +#include + +#endif + diff --git a/include/jsoncons_ext/msgpack/msgpack_cursor.hpp b/include/jsoncons_ext/msgpack/msgpack_cursor.hpp new file mode 100644 index 0000000..a813429 --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_cursor.hpp @@ -0,0 +1,343 @@ +// Copyright 2018 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_CURSOR_HPP +#define JSONCONS_MSGPACK_MSGPACK_CURSOR_HPP + +#include // std::allocator +#include +#include +#include +#include +#include +#include // std::basic_istream +#include +#include +#include +#include +#include +#include +#include + +namespace jsoncons { +namespace msgpack { + +template> +class basic_msgpack_cursor : public basic_staj_cursor, private virtual ser_context +{ +public: + using source_type = Source; + using char_type = char; + using allocator_type = Allocator; +private: + basic_msgpack_parser parser_; + basic_staj_visitor cursor_visitor_; + basic_json_visitor2_to_visitor_adaptor cursor_handler_adaptor_; + bool eof_; + + // Noncopyable and nonmoveable + basic_msgpack_cursor(const basic_msgpack_cursor&) = delete; + basic_msgpack_cursor& operator=(const basic_msgpack_cursor&) = delete; + +public: + using string_view_type = string_view; + + template + basic_msgpack_cursor(Sourceable&& source, + const msgpack_decode_options& options = msgpack_decode_options(), + const Allocator& alloc = Allocator()) + : parser_(std::forward(source), options, alloc), + cursor_visitor_(accept_all), + cursor_handler_adaptor_(cursor_visitor_, alloc), + eof_(false) + { + if (!done()) + { + next(); + } + } + + // Constructors that set parse error codes + + template + basic_msgpack_cursor(Sourceable&& source, + std::error_code& ec) + : basic_msgpack_cursor(std::allocator_arg, Allocator(), + std::forward(source), + msgpack_decode_options(), + ec) + { + } + + template + basic_msgpack_cursor(Sourceable&& source, + const msgpack_decode_options& options, + std::error_code& ec) + : basic_msgpack_cursor(std::allocator_arg, Allocator(), + std::forward(source), + options, + ec) + { + } + + template + basic_msgpack_cursor(std::allocator_arg_t, const Allocator& alloc, + Sourceable&& source, + const msgpack_decode_options& options, + std::error_code& ec) + : parser_(std::forward(source), options, alloc), + cursor_visitor_(accept_all), + cursor_handler_adaptor_(cursor_visitor_, alloc), + eof_(false) + { + if (!done()) + { + next(ec); + } + } + + void reset() + { + parser_.reset(); + cursor_visitor_.reset(); + cursor_handler_adaptor_.reset(); + eof_ = false; + if (!done()) + { + next(); + } + } + + template + void reset(Sourceable&& source) + { + parser_.reset(std::forward(source)); + cursor_visitor_.reset(); + cursor_handler_adaptor_.reset(); + eof_ = false; + if (!done()) + { + next(); + } + } + + void reset(std::error_code& ec) + { + parser_.reset(); + cursor_visitor_.reset(); + cursor_handler_adaptor_.reset(); + eof_ = false; + if (!done()) + { + next(ec); + } + } + + template + void reset(Sourceable&& source, std::error_code& ec) + { + parser_.reset(std::forward(source)); + cursor_visitor_.reset(); + cursor_handler_adaptor_.reset(); + eof_ = false; + if (!done()) + { + next(ec); + } + } + + bool done() const override + { + return parser_.done(); + } + + const staj_event& current() const override + { + return cursor_visitor_.event(); + } + + void read_to(basic_json_visitor& visitor) override + { + std::error_code ec; + read_to(visitor, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column())); + } + } + + void read_to(basic_json_visitor& visitor, + std::error_code& ec) override + { + if (cursor_visitor_.dump(visitor, *this, ec)) + { + read_next(visitor, ec); + } + } + + void next() override + { + std::error_code ec; + next(ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column())); + } + } + + void next(std::error_code& ec) override + { + read_next(ec); + } + + const ser_context& context() const override + { + return *this; + } + + bool eof() const + { + return eof_; + } + + std::size_t line() const override + { + return parser_.line(); + } + + std::size_t column() const override + { + return parser_.column(); + } + + friend + staj_filter_view operator|(basic_msgpack_cursor& cursor, + std::function pred) + { + return staj_filter_view(cursor, pred); + } + +#if !defined(JSONCONS_NO_DEPRECATED) + + template + JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter") + basic_msgpack_cursor(Sourceable&& source, + std::function filter, + const msgpack_decode_options& options = msgpack_decode_options(), + const Allocator& alloc = Allocator()) + : parser_(std::forward(source), options, alloc), + cursor_visitor_(filter), + cursor_handler_adaptor_(cursor_visitor_, alloc), + eof_(false) + { + if (!done()) + { + next(); + } + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter") + basic_msgpack_cursor(Sourceable&& source, + std::function filter, + std::error_code& ec) + : basic_msgpack_cursor(std::allocator_arg, Allocator(), + std::forward(source), filter, ec) + { + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter") + basic_msgpack_cursor(std::allocator_arg_t, const Allocator& alloc, + Sourceable&& source, + std::function filter, + std::error_code& ec) + : parser_(std::forward(source), alloc), + cursor_visitor_(filter), + cursor_handler_adaptor_(cursor_visitor_, alloc), + eof_(false) + { + if (!done()) + { + next(ec); + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor&)") + void read(basic_json_visitor& visitor) + { + read_to(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor&, std::error_code&)") + void read(basic_json_visitor& visitor, + std::error_code& ec) + { + read_to(visitor, ec); + } +#endif +private: + static bool accept_all(const staj_event&, const ser_context&) + { + return true; + } + + void read_next(std::error_code& ec) + { + if (cursor_visitor_.in_available()) + { + cursor_visitor_.send_available(ec); + } + else + { + parser_.restart(); + while (!parser_.stopped()) + { + parser_.parse(cursor_handler_adaptor_, ec); + if (ec) return; + } + } + } + + void read_next(basic_json_visitor& visitor, std::error_code& ec) + { + { + struct resource_wrapper + { + basic_json_visitor2_to_visitor_adaptor& adaptor; + basic_json_visitor& original; + + resource_wrapper(basic_json_visitor2_to_visitor_adaptor& adaptor, + basic_json_visitor& visitor) + : adaptor(adaptor), original(adaptor.destination()) + { + adaptor.destination(visitor); + } + + ~resource_wrapper() + { + adaptor.destination(original); + } + } wrapper(cursor_handler_adaptor_, visitor); + + parser_.restart(); + while (!parser_.stopped()) + { + parser_.parse(cursor_handler_adaptor_, ec); + if (ec) return; + } + } + } +}; + +using msgpack_stream_cursor = basic_msgpack_cursor; +using msgpack_bytes_cursor = basic_msgpack_cursor; + +} // namespace msgpack +} // namespace jsoncons + +#endif + diff --git a/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp b/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp new file mode 100644 index 0000000..8fce1ca --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp @@ -0,0 +1,259 @@ +// Copyright 2018 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_CURSOR2_HPP +#define JSONCONS_MSGPACK_MSGPACK_CURSOR2_HPP + +#include // std::allocator +#include +#include +#include +#include +#include +#include // std::basic_istream +#include +#include +#include +#include +#include +#include +#include + +namespace jsoncons { +namespace msgpack { + + template> + class basic_msgpack_cursor2 : public basic_staj2_cursor, private virtual ser_context + { + public: + using source_type = Source; + using char_type = char; + using allocator_type = Allocator; + private: + basic_msgpack_parser parser_; + basic_staj2_visitor cursor_visitor_; + bool eof_; + + // Noncopyable and nonmoveable + basic_msgpack_cursor2(const basic_msgpack_cursor2&) = delete; + basic_msgpack_cursor2& operator=(const basic_msgpack_cursor2&) = delete; + + public: + using string_view_type = string_view; + + template + basic_msgpack_cursor2(Sourceable&& source, + const msgpack_decode_options& options = msgpack_decode_options(), + const Allocator& alloc = Allocator()) + : parser_(std::forward(source), options, alloc), + cursor_visitor_(accept_all), + eof_(false) + { + if (!done()) + { + next(); + } + } + + // Constructors that set parse error codes + + template + basic_msgpack_cursor2(Sourceable&& source, + std::error_code& ec) + : basic_msgpack_cursor2(std::allocator_arg, Allocator(), + std::forward(source), + msgpack_decode_options(), + ec) + { + } + + template + basic_msgpack_cursor2(Sourceable&& source, + const msgpack_decode_options& options, + std::error_code& ec) + : basic_msgpack_cursor2(std::allocator_arg, Allocator(), + std::forward(source), + options, + ec) + { + } + + template + basic_msgpack_cursor2(std::allocator_arg_t, const Allocator& alloc, + Sourceable&& source, + const msgpack_decode_options& options, + std::error_code& ec) + : parser_(std::forward(source), options, alloc), + cursor_visitor_(accept_all), + eof_(false) + { + if (!done()) + { + next(ec); + } + } + + void reset() + { + parser_.reset(); + cursor_visitor_.reset(); + eof_ = false; + if (!done()) + { + next(); + } + } + + template + void reset(Sourceable&& source) + { + parser_.reset(std::forward(source)); + cursor_visitor_.reset(); + eof_ = false; + if (!done()) + { + next(); + } + } + + void reset(std::error_code& ec) + { + parser_.reset(); + cursor_visitor_.reset(); + eof_ = false; + if (!done()) + { + next(ec); + } + } + + template + void reset(Sourceable&& source, std::error_code& ec) + { + parser_.reset(std::forward(source)); + cursor_visitor_.reset(); + eof_ = false; + if (!done()) + { + next(ec); + } + } + + bool done() const override + { + return parser_.done(); + } + + const staj2_event& current() const override + { + return cursor_visitor_.event(); + } + + void read_to(basic_json_visitor2& visitor) override + { + std::error_code ec; + read_to(visitor, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column())); + } + } + + void read_to(basic_json_visitor2& visitor, + std::error_code& ec) override + { + if (cursor_visitor_.dump(visitor, *this, ec)) + { + read_next(visitor, ec); + } + } + + void next() override + { + std::error_code ec; + next(ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column())); + } + } + + void next(std::error_code& ec) override + { + read_next(ec); + } + + const ser_context& context() const override + { + return *this; + } + + bool eof() const + { + return eof_; + } + + std::size_t line() const override + { + return parser_.line(); + } + + std::size_t column() const override + { + return parser_.column(); + } + + friend + staj2_filter_view operator|(basic_msgpack_cursor2& cursor, + std::function pred) + { + return staj2_filter_view(cursor, pred); + } + + private: + static bool accept_all(const staj2_event&, const ser_context&) + { + return true; + } + + void read_next(std::error_code& ec) + { + if (cursor_visitor_.in_available()) + { + cursor_visitor_.send_available(ec); + } + else + { + parser_.restart(); + while (!parser_.stopped()) + { + parser_.parse(cursor_visitor_, ec); + if (ec) return; + } + } + } + + void read_next(basic_json_visitor2& visitor, std::error_code& ec) + { + { + parser_.restart(); + while (!parser_.stopped()) + { + parser_.parse(visitor, ec); + if (ec) return; + } + } + } + }; + + using msgpack_stream_cursor2 = basic_msgpack_cursor2; + using msgpack_bytes_cursor2 = basic_msgpack_cursor2; + +} // namespace msgpack +} // namespace jsoncons + +#endif + diff --git a/include/jsoncons_ext/msgpack/msgpack_encoder.hpp b/include/jsoncons_ext/msgpack/msgpack_encoder.hpp new file mode 100644 index 0000000..34e882b --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_encoder.hpp @@ -0,0 +1,753 @@ +// Copyright 2018 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_ENCODER_HPP +#define JSONCONS_MSGPACK_MSGPACK_ENCODER_HPP + +#include +#include +#include // std::numeric_limits +#include +#include // std::move +#include +#include +#include +#include +#include +#include +#include +#include + +namespace jsoncons { +namespace msgpack { + + enum class msgpack_container_type {object, array}; + + template> + class basic_msgpack_encoder final : public basic_json_visitor + { + enum class decimal_parse_state { start, integer, exp1, exp2, fraction1 }; + + static constexpr int64_t nanos_in_milli = 1000000; + static constexpr int64_t nanos_in_second = 1000000000; + static constexpr int64_t millis_in_second = 1000; + public: + using allocator_type = Allocator; + using char_type = char; + using typename basic_json_visitor::string_view_type; + using sink_type = Sink; + + private: + struct stack_item + { + msgpack_container_type type_; + std::size_t length_; + std::size_t count_; + + stack_item(msgpack_container_type type, std::size_t length = 0) noexcept + : type_(type), length_(length), count_(0) + { + } + + std::size_t length() const + { + return length_; + } + + std::size_t count() const + { + return count_; + } + + bool is_object() const + { + return type_ == msgpack_container_type::object; + } + }; + + Sink sink_; + const msgpack_encode_options options_; + allocator_type alloc_; + + std::vector stack_; + int nesting_depth_; + + // Noncopyable and nonmoveable + basic_msgpack_encoder(const basic_msgpack_encoder&) = delete; + basic_msgpack_encoder& operator=(const basic_msgpack_encoder&) = delete; + public: + explicit basic_msgpack_encoder(Sink&& sink, + const Allocator& alloc = Allocator()) + : basic_msgpack_encoder(std::forward(sink), msgpack_encode_options(), alloc) + { + } + + explicit basic_msgpack_encoder(Sink&& sink, + const msgpack_encode_options& options, + const Allocator& alloc = Allocator()) + : sink_(std::forward(sink)), + options_(options), + alloc_(alloc), + nesting_depth_(0) + { + } + + ~basic_msgpack_encoder() noexcept + { + sink_.flush(); + } + + void reset() + { + stack_.clear(); + nesting_depth_ = 0; + } + + void reset(Sink&& sink) + { + sink_ = std::move(sink); + reset(); + } + + private: + // Implementing methods + + void visit_flush() override + { + sink_.flush(); + } + + bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override + { + ec = msgpack_errc::object_length_required; + return false; + } + + bool visit_begin_object(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) override + { + if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth())) + { + ec = msgpack_errc::max_nesting_depth_exceeded; + return false; + } + stack_.emplace_back(msgpack_container_type::object, length); + + if (length <= 15) + { + // fixmap + sink_.push_back(jsoncons::msgpack::msgpack_type::fixmap_base_type | (length & 0xf)); + } + else if (length <= 65535) + { + // map 16 + sink_.push_back(jsoncons::msgpack::msgpack_type::map16_type); + binary::native_to_big(static_cast(length), + std::back_inserter(sink_)); + } + else if (length <= 4294967295) + { + // map 32 + sink_.push_back(jsoncons::msgpack::msgpack_type::map32_type); + binary::native_to_big(static_cast(length), + std::back_inserter(sink_)); + } + + return true; + } + + bool visit_end_object(const ser_context&, std::error_code& ec) override + { + JSONCONS_ASSERT(!stack_.empty()); + --nesting_depth_; + + if (stack_.back().count() < stack_.back().length()) + { + ec = msgpack_errc::too_few_items; + return false; + } + else if (stack_.back().count() > stack_.back().length()) + { + ec = msgpack_errc::too_many_items; + return false; + } + + stack_.pop_back(); + end_value(); + return true; + } + + bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override + { + ec = msgpack_errc::array_length_required; + return false; + } + + bool visit_begin_array(std::size_t length, semantic_tag, const ser_context&, std::error_code& ec) override + { + if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth())) + { + ec = msgpack_errc::max_nesting_depth_exceeded; + return false; + } + stack_.emplace_back(msgpack_container_type::array, length); + if (length <= 15) + { + // fixarray + sink_.push_back(jsoncons::msgpack::msgpack_type::fixarray_base_type | (length & 0xf)); + } + else if (length <= (std::numeric_limits::max)()) + { + // array 16 + sink_.push_back(jsoncons::msgpack::msgpack_type::array16_type); + binary::native_to_big(static_cast(length),std::back_inserter(sink_)); + } + else if (length <= (std::numeric_limits::max)()) + { + // array 32 + sink_.push_back(jsoncons::msgpack::msgpack_type::array32_type); + binary::native_to_big(static_cast(length),std::back_inserter(sink_)); + } + return true; + } + + bool visit_end_array(const ser_context&, std::error_code& ec) override + { + JSONCONS_ASSERT(!stack_.empty()); + + --nesting_depth_; + + if (stack_.back().count() < stack_.back().length()) + { + ec = msgpack_errc::too_few_items; + return false; + } + else if (stack_.back().count() > stack_.back().length()) + { + ec = msgpack_errc::too_many_items; + return false; + } + + stack_.pop_back(); + end_value(); + return true; + } + + bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override + { + write_string_value(name); + return true; + } + + bool visit_null(semantic_tag, const ser_context&, std::error_code&) override + { + // nil + sink_.push_back(jsoncons::msgpack::msgpack_type::nil_type); + end_value(); + return true; + } + + void write_timestamp(int64_t seconds, int64_t nanoseconds) + { + if ((seconds >> 34) == 0) + { + uint64_t data64 = (nanoseconds << 34) | seconds; + if ((data64 & 0xffffffff00000000L) == 0) + { + // timestamp 32 + sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type); + sink_.push_back(0xff); + binary::native_to_big(static_cast(data64), std::back_inserter(sink_)); + } + else + { + // timestamp 64 + sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type); + sink_.push_back(0xff); + binary::native_to_big(static_cast(data64), std::back_inserter(sink_)); + } + } + else + { + // timestamp 96 + sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type); + sink_.push_back(0x0c); // 12 + sink_.push_back(0xff); + binary::native_to_big(static_cast(nanoseconds), std::back_inserter(sink_)); + binary::native_to_big(static_cast(seconds), std::back_inserter(sink_)); + } + } + + bool visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code& ec) override + { + switch (tag) + { + case semantic_tag::epoch_second: + { + int64_t seconds; + auto result = jsoncons::detail::to_integer(sv.data(), sv.length(), seconds); + if (!result) + { + ec = msgpack_errc::invalid_timestamp; + return false; + } + write_timestamp(seconds, 0); + break; + } + case semantic_tag::epoch_milli: + { + bigint n = bigint::from_string(sv.data(), sv.length()); + if (n != 0) + { + bigint q; + bigint rem; + n.divide(millis_in_second, q, rem, true); + int64_t seconds = static_cast(q); + int64_t nanoseconds = static_cast(rem) * nanos_in_milli; + if (nanoseconds < 0) + { + nanoseconds = -nanoseconds; + } + write_timestamp(seconds, nanoseconds); + } + else + { + write_timestamp(0, 0); + } + break; + } + case semantic_tag::epoch_nano: + { + bigint n = bigint::from_string(sv.data(), sv.length()); + if (n != 0) + { + bigint q; + bigint rem; + n.divide(nanos_in_second, q, rem, true); + int64_t seconds = static_cast(q); + int64_t nanoseconds = static_cast(rem); + if (nanoseconds < 0) + { + nanoseconds = -nanoseconds; + } + write_timestamp(seconds, nanoseconds); + } + else + { + write_timestamp(0, 0); + } + break; + } + default: + { + write_string_value(sv); + end_value(); + break; + } + } + return true; + } + + void write_string_value(const string_view_type& sv) + { + auto sink = unicode_traits::validate(sv.data(), sv.size()); + if (sink.ec != unicode_traits::conv_errc()) + { + JSONCONS_THROW(ser_error(msgpack_errc::invalid_utf8_text_string)); + } + + const size_t length = sv.length(); + if (length <= 31) + { + // fixstr stores a byte array whose length is upto 31 bytes + sink_.push_back(jsoncons::msgpack::msgpack_type::fixstr_base_type | static_cast(length)); + } + else if (length <= (std::numeric_limits::max)()) + { + // str 8 stores a byte array whose length is upto (2^8)-1 bytes + sink_.push_back(jsoncons::msgpack::msgpack_type::str8_type); + sink_.push_back(static_cast(length)); + } + else if (length <= (std::numeric_limits::max)()) + { + // str 16 stores a byte array whose length is upto (2^16)-1 bytes + sink_.push_back(jsoncons::msgpack::msgpack_type::str16_type); + binary::native_to_big(static_cast(length), std::back_inserter(sink_)); + } + else if (length <= (std::numeric_limits::max)()) + { + // str 32 stores a byte array whose length is upto (2^32)-1 bytes + sink_.push_back(jsoncons::msgpack::msgpack_type::str32_type); + binary::native_to_big(static_cast(length),std::back_inserter(sink_)); + } + + for (auto c : sv) + { + sink_.push_back(c); + } + } + + bool visit_byte_string(const byte_string_view& b, + semantic_tag, + const ser_context&, + std::error_code&) override + { + + const std::size_t length = b.size(); + if (length <= (std::numeric_limits::max)()) + { + // bin 8 stores a byte array whose length is upto (2^8)-1 bytes + sink_.push_back(jsoncons::msgpack::msgpack_type::bin8_type); + sink_.push_back(static_cast(length)); + } + else if (length <= (std::numeric_limits::max)()) + { + // bin 16 stores a byte array whose length is upto (2^16)-1 bytes + sink_.push_back(jsoncons::msgpack::msgpack_type::bin16_type); + binary::native_to_big(static_cast(length), std::back_inserter(sink_)); + } + else if (length <= (std::numeric_limits::max)()) + { + // bin 32 stores a byte array whose length is upto (2^32)-1 bytes + sink_.push_back(jsoncons::msgpack::msgpack_type::bin32_type); + binary::native_to_big(static_cast(length),std::back_inserter(sink_)); + } + + for (auto c : b) + { + sink_.push_back(c); + } + + end_value(); + return true; + } + + bool visit_byte_string(const byte_string_view& b, + uint64_t ext_tag, + const ser_context&, + std::error_code&) override + { + const std::size_t length = b.size(); + switch (length) + { + case 1: + sink_.push_back(jsoncons::msgpack::msgpack_type::fixext1_type); + sink_.push_back(static_cast(ext_tag)); + break; + case 2: + sink_.push_back(jsoncons::msgpack::msgpack_type::fixext2_type); + sink_.push_back(static_cast(ext_tag)); + break; + case 4: + sink_.push_back(jsoncons::msgpack::msgpack_type::fixext4_type); + sink_.push_back(static_cast(ext_tag)); + break; + case 8: + sink_.push_back(jsoncons::msgpack::msgpack_type::fixext8_type); + sink_.push_back(static_cast(ext_tag)); + break; + case 16: + sink_.push_back(jsoncons::msgpack::msgpack_type::fixext16_type); + sink_.push_back(static_cast(ext_tag)); + break; + default: + if (length <= (std::numeric_limits::max)()) + { + sink_.push_back(jsoncons::msgpack::msgpack_type::ext8_type); + sink_.push_back(static_cast(length)); + sink_.push_back(static_cast(ext_tag)); + } + else if (length <= (std::numeric_limits::max)()) + { + sink_.push_back(jsoncons::msgpack::msgpack_type::ext16_type); + binary::native_to_big(static_cast(length), std::back_inserter(sink_)); + sink_.push_back(static_cast(ext_tag)); + } + else if (length <= (std::numeric_limits::max)()) + { + sink_.push_back(jsoncons::msgpack::msgpack_type::ext32_type); + binary::native_to_big(static_cast(length),std::back_inserter(sink_)); + sink_.push_back(static_cast(ext_tag)); + } + break; + } + + for (auto c : b) + { + sink_.push_back(c); + } + + end_value(); + return true; + } + + bool visit_double(double val, + semantic_tag, + const ser_context&, + std::error_code&) override + { + float valf = (float)val; + if ((double)valf == val) + { + // float 32 + sink_.push_back(jsoncons::msgpack::msgpack_type::float32_type); + binary::native_to_big(valf,std::back_inserter(sink_)); + } + else + { + // float 64 + sink_.push_back(jsoncons::msgpack::msgpack_type::float64_type); + binary::native_to_big(val,std::back_inserter(sink_)); + } + + // write double + + end_value(); + return true; + } + + bool visit_int64(int64_t val, + semantic_tag tag, + const ser_context&, + std::error_code&) override + { + switch (tag) + { + case semantic_tag::epoch_second: + write_timestamp(val, 0); + break; + case semantic_tag::epoch_milli: + { + if (val != 0) + { + auto dv = std::div(val,millis_in_second); + int64_t seconds = dv.quot; + int64_t nanoseconds = dv.rem*nanos_in_milli; + if (nanoseconds < 0) + { + nanoseconds = -nanoseconds; + } + write_timestamp(seconds, nanoseconds); + } + else + { + write_timestamp(0, 0); + } + break; + } + case semantic_tag::epoch_nano: + { + if (val != 0) + { + auto dv = std::div(val,static_cast(nanos_in_second)); + int64_t seconds = dv.quot; + int64_t nanoseconds = dv.rem; + if (nanoseconds < 0) + { + nanoseconds = -nanoseconds; + } + write_timestamp(seconds, nanoseconds); + } + else + { + write_timestamp(0, 0); + } + break; + } + default: + { + if (val >= 0) + { + if (val <= 0x7f) + { + // positive fixnum stores 7-bit positive integer + sink_.push_back(static_cast(val)); + } + else if (val <= (std::numeric_limits::max)()) + { + // uint 8 stores a 8-bit unsigned integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type); + sink_.push_back(static_cast(val)); + } + else if (val <= (std::numeric_limits::max)()) + { + // uint 16 stores a 16-bit big-endian unsigned integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + else if (val <= (std::numeric_limits::max)()) + { + // uint 32 stores a 32-bit big-endian unsigned integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + else if (val <= (std::numeric_limits::max)()) + { + // int 64 stores a 64-bit big-endian signed integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + } + else + { + if (val >= -32) + { + // negative fixnum stores 5-bit negative integer + binary::native_to_big(static_cast(val), std::back_inserter(sink_)); + } + else if (val >= (std::numeric_limits::lowest)()) + { + // int 8 stores a 8-bit signed integer + sink_.push_back(jsoncons::msgpack::msgpack_type::int8_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + else if (val >= (std::numeric_limits::lowest)()) + { + // int 16 stores a 16-bit big-endian signed integer + sink_.push_back(jsoncons::msgpack::msgpack_type::int16_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + else if (val >= (std::numeric_limits::lowest)()) + { + // int 32 stores a 32-bit big-endian signed integer + sink_.push_back(jsoncons::msgpack::msgpack_type::int32_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + else if (val >= (std::numeric_limits::lowest)()) + { + // int 64 stores a 64-bit big-endian signed integer + sink_.push_back(jsoncons::msgpack::msgpack_type::int64_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + } + } + break; + } + end_value(); + return true; + } + + bool visit_uint64(uint64_t val, + semantic_tag tag, + const ser_context&, + std::error_code&) override + { + switch (tag) + { + case semantic_tag::epoch_second: + write_timestamp(static_cast(val), 0); + break; + case semantic_tag::epoch_milli: + { + if (val != 0) + { + auto dv = std::div(static_cast(val), static_cast(millis_in_second)); + int64_t seconds = dv.quot; + int64_t nanoseconds = dv.rem*nanos_in_milli; + if (nanoseconds < 0) + { + nanoseconds = -nanoseconds; + } + write_timestamp(seconds, nanoseconds); + } + else + { + write_timestamp(0, 0); + } + break; + } + case semantic_tag::epoch_nano: + { + if (val != 0) + { + auto dv = std::div(static_cast(val), static_cast(nanos_in_second)); + int64_t seconds = dv.quot; + int64_t nanoseconds = dv.rem; + if (nanoseconds < 0) + { + nanoseconds = -nanoseconds; + } + write_timestamp(seconds, nanoseconds); + } + else + { + write_timestamp(0, 0); + } + break; + } + default: + { + if (val <= static_cast((std::numeric_limits::max)())) + { + // positive fixnum stores 7-bit positive integer + sink_.push_back(static_cast(val)); + } + else if (val <= (std::numeric_limits::max)()) + { + // uint 8 stores a 8-bit unsigned integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint8_type); + sink_.push_back(static_cast(val)); + } + else if (val <= (std::numeric_limits::max)()) + { + // uint 16 stores a 16-bit big-endian unsigned integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint16_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + else if (val <= (std::numeric_limits::max)()) + { + // uint 32 stores a 32-bit big-endian unsigned integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint32_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + else if (val <= (std::numeric_limits::max)()) + { + // uint 64 stores a 64-bit big-endian unsigned integer + sink_.push_back(jsoncons::msgpack::msgpack_type::uint64_type); + binary::native_to_big(static_cast(val),std::back_inserter(sink_)); + } + break; + } + } + end_value(); + return true; + } + + bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) override + { + // true and false + sink_.push_back(static_cast(val ? jsoncons::msgpack::msgpack_type::true_type : jsoncons::msgpack::msgpack_type::false_type)); + + end_value(); + return true; + } + + void end_value() + { + if (!stack_.empty()) + { + ++stack_.back().count_; + } + } + }; + + using msgpack_stream_encoder = basic_msgpack_encoder; + using msgpack_bytes_encoder = basic_msgpack_encoder>>; + + #if !defined(JSONCONS_NO_DEPRECATED) + JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_encoder") typedef msgpack_bytes_encoder msgpack_bytes_serializer; + + template + using basic_msgpack_serializer = basic_msgpack_encoder; + + JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_encoder") typedef msgpack_stream_encoder msgpack_encoder; + JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_encoder") typedef msgpack_stream_encoder msgpack_serializer; + JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_encoder") typedef msgpack_bytes_encoder msgpack_buffer_serializer; + #endif + +} // namespace msgpack +} // namespace jsoncons + +#endif diff --git a/include/jsoncons_ext/msgpack/msgpack_error.hpp b/include/jsoncons_ext/msgpack/msgpack_error.hpp new file mode 100644 index 0000000..80c76b6 --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_error.hpp @@ -0,0 +1,94 @@ +/// Copyright 2018 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_ERROR_HPP +#define JSONCONS_MSGPACK_MSGPACK_ERROR_HPP + +#include +#include + +namespace jsoncons { namespace msgpack { + +enum class msgpack_errc +{ + success = 0, + unexpected_eof = 1, + source_error, + invalid_utf8_text_string, + array_length_required, + object_length_required, + too_many_items, + too_few_items, + max_nesting_depth_exceeded, + length_is_negative, + invalid_timestamp, + unknown_type +}; + +class msgpack_error_category_impl + : public std::error_category +{ +public: + const char* name() const noexcept override + { + return "jsoncons/msgpack"; + } + std::string message(int ev) const override + { + switch (static_cast(ev)) + { + case msgpack_errc::unexpected_eof: + return "Unexpected end of file"; + case msgpack_errc::source_error: + return "Source error"; + case msgpack_errc::invalid_utf8_text_string: + return "Illegal UTF-8 encoding in text string"; + case msgpack_errc::array_length_required: + return "MessagePack encoder requires array length"; + case msgpack_errc::object_length_required: + return "MessagePack encoder requires object length"; + case msgpack_errc::too_many_items: + return "Too many items were added to a MessagePack object or array"; + case msgpack_errc::too_few_items: + return "Too few items were added to a MessagePack object or array"; + case msgpack_errc::max_nesting_depth_exceeded: + return "Data item nesting exceeds limit in options"; + case msgpack_errc::length_is_negative: + return "Request for the length of an array, map or string returned a negative result"; + case msgpack_errc::invalid_timestamp: + return "Invalid timestamp"; + case msgpack_errc::unknown_type: + return "An unknown type was found in the stream"; + default: + return "Unknown MessagePack parser error"; + } + } +}; + +inline +const std::error_category& msgpack_error_category() +{ + static msgpack_error_category_impl instance; + return instance; +} + +inline +std::error_code make_error_code(msgpack_errc e) +{ + return std::error_code(static_cast(e),msgpack_error_category()); +} + + +}} + +namespace std { + template<> + struct is_error_code_enum : public true_type + { + }; +} + +#endif diff --git a/include/jsoncons_ext/msgpack/msgpack_options.hpp b/include/jsoncons_ext/msgpack/msgpack_options.hpp new file mode 100644 index 0000000..17bddf1 --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_options.hpp @@ -0,0 +1,74 @@ +// Copyright 2019 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_OPTIONS_HPP +#define JSONCONS_MSGPACK_MSGPACK_OPTIONS_HPP + +#include +#include // std::numeric_limits +#include +#include + +namespace jsoncons { namespace msgpack { + +class msgpack_options; + +class msgpack_options_common +{ + friend class msgpack_options; + + int max_nesting_depth_; +protected: + virtual ~msgpack_options_common() = default; + + msgpack_options_common() + : max_nesting_depth_(1024) + { + } + + msgpack_options_common(const msgpack_options_common&) = default; + msgpack_options_common& operator=(const msgpack_options_common&) = default; + msgpack_options_common(msgpack_options_common&&) = default; + msgpack_options_common& operator=(msgpack_options_common&&) = default; +public: + int max_nesting_depth() const + { + return max_nesting_depth_; + } +}; + +class msgpack_decode_options : public virtual msgpack_options_common +{ + friend class msgpack_options; +public: + msgpack_decode_options() + { + } +}; + +class msgpack_encode_options : public virtual msgpack_options_common +{ + friend class msgpack_options; +public: + msgpack_encode_options() + { + } +}; + +class msgpack_options final : public msgpack_decode_options, public msgpack_encode_options +{ +public: + using msgpack_options_common::max_nesting_depth; + + msgpack_options& max_nesting_depth(int value) + { + this->max_nesting_depth_ = value; + return *this; + } +}; + +}} +#endif diff --git a/include/jsoncons_ext/msgpack/msgpack_parser.hpp b/include/jsoncons_ext/msgpack/msgpack_parser.hpp new file mode 100644 index 0000000..cf2d507 --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_parser.hpp @@ -0,0 +1,748 @@ +// Copyright 2017 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_PARSER_HPP +#define JSONCONS_MSGPACK_MSGPACK_PARSER_HPP + +#include +#include +#include +#include // std::move +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace jsoncons { namespace msgpack { + +enum class parse_mode {root,accept,array,map_key,map_value}; + +struct parse_state +{ + parse_mode mode; + std::size_t length; + std::size_t index; + + parse_state(parse_mode mode, std::size_t length) noexcept + : mode(mode), length(length), index(0) + { + } + + parse_state(const parse_state&) = default; + parse_state(parse_state&&) = default; +}; + +template > +class basic_msgpack_parser : public ser_context +{ + using char_type = char; + using char_traits_type = std::char_traits; + using temp_allocator_type = Allocator; + using char_allocator_type = typename std::allocator_traits:: template rebind_alloc; + using byte_allocator_type = typename std::allocator_traits:: template rebind_alloc; + using int64_allocator_type = typename std::allocator_traits:: template rebind_alloc; + using parse_state_allocator_type = typename std::allocator_traits:: template rebind_alloc; + + static constexpr int64_t nanos_in_second = 1000000000; + + Source source_; + msgpack_decode_options options_; + bool more_; + bool done_; + std::basic_string,char_allocator_type> text_buffer_; + std::vector bytes_buffer_; + std::vector state_stack_; + int nesting_depth_; + +public: + template + basic_msgpack_parser(Sourceable&& source, + const msgpack_decode_options& options = msgpack_decode_options(), + const Allocator alloc = Allocator()) + : source_(std::forward(source)), + options_(options), + more_(true), + done_(false), + text_buffer_(alloc), + bytes_buffer_(alloc), + state_stack_(alloc), + nesting_depth_(0) + { + state_stack_.emplace_back(parse_mode::root,0); + } + + void restart() + { + more_ = true; + } + + void reset() + { + more_ = true; + done_ = false; + text_buffer_.clear(); + bytes_buffer_.clear(); + state_stack_.clear(); + state_stack_.emplace_back(parse_mode::root,0); + nesting_depth_ = 0; + } + + template + void reset(Sourceable&& source) + { + source_ = std::forward(source); + reset(); + } + + bool done() const + { + return done_; + } + + bool stopped() const + { + return !more_; + } + + std::size_t line() const override + { + return 0; + } + + std::size_t column() const override + { + return source_.position(); + } + + void parse(json_visitor2& visitor, std::error_code& ec) + { + while (!done_ && more_) + { + switch (state_stack_.back().mode) + { + case parse_mode::array: + { + if (state_stack_.back().index < state_stack_.back().length) + { + ++state_stack_.back().index; + read_item(visitor, ec); + if (ec) + { + return; + } + } + else + { + end_array(visitor, ec); + } + break; + } + case parse_mode::map_key: + { + if (state_stack_.back().index < state_stack_.back().length) + { + ++state_stack_.back().index; + state_stack_.back().mode = parse_mode::map_value; + read_item(visitor, ec); + if (ec) + { + return; + } + } + else + { + end_object(visitor, ec); + } + break; + } + case parse_mode::map_value: + { + state_stack_.back().mode = parse_mode::map_key; + read_item(visitor, ec); + if (ec) + { + return; + } + break; + } + case parse_mode::root: + { + state_stack_.back().mode = parse_mode::accept; + read_item(visitor, ec); + if (ec) + { + return; + } + break; + } + case parse_mode::accept: + { + JSONCONS_ASSERT(state_stack_.size() == 1); + state_stack_.clear(); + more_ = false; + done_ = true; + visitor.flush(); + break; + } + } + } + } +private: + + void read_item(json_visitor2& visitor, std::error_code& ec) + { + if (source_.is_error()) + { + ec = msgpack_errc::source_error; + more_ = false; + return; + } + + uint8_t type; + if (source_.read(&type, 1) == 0) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + + if (type <= 0xbf) + { + if (type <= 0x7f) + { + // positive fixint + more_ = visitor.uint64_value(type, semantic_tag::none, *this, ec); + } + else if (type <= 0x8f) + { + begin_object(visitor,type,ec); // fixmap + } + else if (type <= 0x9f) + { + begin_array(visitor,type,ec); // fixarray + } + else + { + // fixstr + const size_t len = type & 0x1f; + + text_buffer_.clear(); + + if (source_reader::read(source_,text_buffer_,len) != static_cast(len)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + + auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size()); + if (result.ec != unicode_traits::conv_errc()) + { + ec = msgpack_errc::invalid_utf8_text_string; + more_ = false; + return; + } + more_ = visitor.string_value(jsoncons::basic_string_view(text_buffer_.data(),text_buffer_.length()), semantic_tag::none, *this, ec); + } + } + else if (type >= 0xe0) + { + // negative fixint + more_ = visitor.int64_value(static_cast(type), semantic_tag::none, *this, ec); + } + else + { + switch (type) + { + case jsoncons::msgpack::msgpack_type::nil_type: + { + more_ = visitor.null_value(semantic_tag::none, *this, ec); + break; + } + case jsoncons::msgpack::msgpack_type::true_type: + { + more_ = visitor.bool_value(true, semantic_tag::none, *this, ec); + break; + } + case jsoncons::msgpack::msgpack_type::false_type: + { + more_ = visitor.bool_value(false, semantic_tag::none, *this, ec); + break; + } + case jsoncons::msgpack::msgpack_type::float32_type: + { + uint8_t buf[sizeof(float)]; + if (source_.read(buf, sizeof(float)) != sizeof(float)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + float val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.double_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::float64_type: + { + uint8_t buf[sizeof(double)]; + if (source_.read(buf, sizeof(double)) != sizeof(double)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + double val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.double_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::uint8_type: + { + uint8_t b; + if (source_.read(&b, 1) == 0) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + more_ = visitor.uint64_value(b, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::uint16_type: + { + uint8_t buf[sizeof(uint16_t)]; + if (source_.read(buf, sizeof(uint16_t)) !=sizeof(uint16_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + uint16_t val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.uint64_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::uint32_type: + { + uint8_t buf[sizeof(uint32_t)]; + if (source_.read(buf, sizeof(uint32_t)) != sizeof(uint32_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + uint32_t val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.uint64_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::uint64_type: + { + uint8_t buf[sizeof(uint64_t)]; + if (source_.read(buf, sizeof(uint64_t)) != sizeof(uint64_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + uint64_t val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.uint64_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::int8_type: + { + uint8_t buf[sizeof(int8_t)]; + if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + int8_t val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.int64_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::int16_type: + { + uint8_t buf[sizeof(int16_t)]; + if (source_.read(buf, sizeof(int16_t)) != sizeof(int16_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + int16_t val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.int64_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::int32_type: + { + uint8_t buf[sizeof(int32_t)]; + if (source_.read(buf, sizeof(int32_t)) != sizeof(int32_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + int32_t val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.int64_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::int64_type: + { + uint8_t buf[sizeof(int64_t)]; + if (source_.read(buf, sizeof(int64_t)) != sizeof(int64_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + int64_t val = binary::big_to_native(buf, sizeof(buf)); + more_ = visitor.int64_value(val, semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::str8_type: + case jsoncons::msgpack::msgpack_type::str16_type: + case jsoncons::msgpack::msgpack_type::str32_type: + { + std::size_t len = get_size(type, ec); + if (!more_) + { + return; + } + + text_buffer_.clear(); + if (source_reader::read(source_,text_buffer_,len) != static_cast(len)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + + auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size()); + if (result.ec != unicode_traits::conv_errc()) + { + ec = msgpack_errc::invalid_utf8_text_string; + more_ = false; + return; + } + more_ = visitor.string_value(jsoncons::basic_string_view(text_buffer_.data(),text_buffer_.length()), semantic_tag::none, *this, ec); + break; + } + + case jsoncons::msgpack::msgpack_type::bin8_type: + case jsoncons::msgpack::msgpack_type::bin16_type: + case jsoncons::msgpack::msgpack_type::bin32_type: + { + std::size_t len = get_size(type,ec); + if (!more_) + { + return; + } + bytes_buffer_.clear(); + if (source_reader::read(source_,bytes_buffer_,len) != static_cast(len)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + + more_ = visitor.byte_string_value(byte_string_view(bytes_buffer_.data(),bytes_buffer_.size()), + semantic_tag::none, + *this, + ec); + break; + } + case jsoncons::msgpack::msgpack_type::fixext1_type: + case jsoncons::msgpack::msgpack_type::fixext2_type: + case jsoncons::msgpack::msgpack_type::fixext4_type: + case jsoncons::msgpack::msgpack_type::fixext8_type: + case jsoncons::msgpack::msgpack_type::fixext16_type: + case jsoncons::msgpack::msgpack_type::ext8_type: + case jsoncons::msgpack::msgpack_type::ext16_type: + case jsoncons::msgpack::msgpack_type::ext32_type: + { + std::size_t len = get_size(type,ec); + if (!more_) + { + return; + } + + // type + uint8_t buf[sizeof(int8_t)]; + if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + + int8_t ext_type = binary::big_to_native(buf, sizeof(buf)); + + bool is_timestamp = false; + if (ext_type == -1) + { + is_timestamp = true;; + } + + // payload + if (is_timestamp && len == 4) + { + uint8_t buf32[sizeof(uint32_t)]; + if (source_.read(buf32, sizeof(uint32_t)) != sizeof(uint32_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + uint32_t val = binary::big_to_native(buf32, sizeof(buf32)); + more_ = visitor.uint64_value(val, semantic_tag::epoch_second, *this, ec); + } + else if (is_timestamp && len == 8) + { + uint8_t buf64[sizeof(uint64_t)]; + if (source_.read(buf64, sizeof(uint64_t)) != sizeof(uint64_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + uint64_t data64 = binary::big_to_native(buf64, sizeof(buf64)); + uint64_t sec = data64 & 0x00000003ffffffffL; + uint64_t nsec = data64 >> 34; + + bigint nano(sec); + nano *= uint64_t(nanos_in_second); + nano += nsec; + text_buffer_.clear(); + nano.write_string(text_buffer_); + more_ = visitor.string_value(text_buffer_, semantic_tag::epoch_nano, *this, ec); + if (!more_) return; + } + else if (is_timestamp && len == 12) + { + uint8_t buf1[sizeof(uint32_t)]; + if (source_.read(buf1, sizeof(uint32_t)) != sizeof(uint32_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + uint32_t nsec = binary::big_to_native(buf1, sizeof(buf1)); + + uint8_t buf2[sizeof(int64_t)]; + if (source_.read(buf2, sizeof(int64_t)) != sizeof(int64_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + int64_t sec = binary::big_to_native(buf2, sizeof(buf2)); + + bigint nano(sec); + + nano *= uint64_t(nanos_in_second); + + if (nano < 0) + { + nano -= nsec; + } + else + { + nano += nsec; + } + + text_buffer_.clear(); + nano.write_string(text_buffer_); + more_ = visitor.string_value(text_buffer_, semantic_tag::epoch_nano, *this, ec); + if (!more_) return; + } + else + { + bytes_buffer_.clear(); + if (source_reader::read(source_,bytes_buffer_,len) != static_cast(len)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return; + } + + more_ = visitor.byte_string_value(byte_string_view(bytes_buffer_.data(),bytes_buffer_.size()), + static_cast(ext_type), + *this, + ec); + } + break; + } + + case jsoncons::msgpack::msgpack_type::array16_type: + case jsoncons::msgpack::msgpack_type::array32_type: + { + begin_array(visitor,type,ec); + break; + } + + case jsoncons::msgpack::msgpack_type::map16_type : + case jsoncons::msgpack::msgpack_type::map32_type : + { + begin_object(visitor, type, ec); + break; + } + + default: + { + ec = msgpack_errc::unknown_type; + more_ = false; + return; + } + } + } + } + + void begin_array(json_visitor2& visitor, uint8_t type, std::error_code& ec) + { + if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth())) + { + ec = msgpack_errc::max_nesting_depth_exceeded; + more_ = false; + return; + } + std::size_t length = get_size(type, ec); + if (!more_) + { + return; + } + state_stack_.emplace_back(parse_mode::array,length); + more_ = visitor.begin_array(length, semantic_tag::none, *this, ec); + } + + void end_array(json_visitor2& visitor, std::error_code& ec) + { + --nesting_depth_; + + more_ = visitor.end_array(*this, ec); + state_stack_.pop_back(); + } + + void begin_object(json_visitor2& visitor, uint8_t type, std::error_code& ec) + { + if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth())) + { + ec = msgpack_errc::max_nesting_depth_exceeded; + more_ = false; + return; + } + std::size_t length = get_size(type, ec); + if (!more_) + { + return; + } + state_stack_.emplace_back(parse_mode::map_key,length); + more_ = visitor.begin_object(length, semantic_tag::none, *this, ec); + } + + void end_object(json_visitor2& visitor, std::error_code& ec) + { + --nesting_depth_; + more_ = visitor.end_object(*this, ec); + state_stack_.pop_back(); + } + + std::size_t get_size(uint8_t type, std::error_code& ec) + { + switch (type) + { + case jsoncons::msgpack::msgpack_type::str8_type: + case jsoncons::msgpack::msgpack_type::bin8_type: + case jsoncons::msgpack::msgpack_type::ext8_type: + { + uint8_t buf[sizeof(int8_t)]; + if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return 0; + } + uint8_t len = binary::big_to_native(buf, sizeof(buf)); + return static_cast(len); + } + + case jsoncons::msgpack::msgpack_type::str16_type: + case jsoncons::msgpack::msgpack_type::bin16_type: + case jsoncons::msgpack::msgpack_type::ext16_type: + case jsoncons::msgpack::msgpack_type::array16_type: + case jsoncons::msgpack::msgpack_type::map16_type: + { + uint8_t buf[sizeof(int16_t)]; + if (source_.read(buf, sizeof(int16_t)) != sizeof(int16_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return 0; + } + uint16_t len = binary::big_to_native(buf, sizeof(buf)); + return static_cast(len); + } + + case jsoncons::msgpack::msgpack_type::str32_type: + case jsoncons::msgpack::msgpack_type::bin32_type: + case jsoncons::msgpack::msgpack_type::ext32_type: + case jsoncons::msgpack::msgpack_type::array32_type: + case jsoncons::msgpack::msgpack_type::map32_type : + { + uint8_t buf[sizeof(int32_t)]; + if (source_.read(buf, sizeof(int32_t)) != sizeof(int32_t)) + { + ec = msgpack_errc::unexpected_eof; + more_ = false; + return 0; + } + uint32_t len = binary::big_to_native(buf, sizeof(buf)); + return static_cast(len); + } + case jsoncons::msgpack::msgpack_type::fixext1_type: + return 1; + case jsoncons::msgpack::msgpack_type::fixext2_type: + return 2; + case jsoncons::msgpack::msgpack_type::fixext4_type: + return 4; + case jsoncons::msgpack::msgpack_type::fixext8_type: + return 8; + case jsoncons::msgpack::msgpack_type::fixext16_type: + return 16; + default: + if ((type > 0x8f && type <= 0x9f) // fixarray + || (type > 0x7f && type <= 0x8f) // fixmap + ) + { + return type & 0x0f; + } + else + { + ec = msgpack_errc::unknown_type; + more_ = false; + return 0; + } + break; + } + } +}; + +}} + +#endif diff --git a/include/jsoncons_ext/msgpack/msgpack_reader.hpp b/include/jsoncons_ext/msgpack/msgpack_reader.hpp new file mode 100644 index 0000000..c0d788a --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_reader.hpp @@ -0,0 +1,116 @@ +// Copyright 2017 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_READER_HPP +#define JSONCONS_MSGPACK_MSGPACK_READER_HPP + +#include +#include +#include +#include // std::move +#include +#include +#include +#include +#include +#include +#include + +namespace jsoncons { namespace msgpack { + +template > +class basic_msgpack_reader +{ + using char_type = char; + + basic_msgpack_parser parser_; + basic_json_visitor2_to_visitor_adaptor adaptor_; + json_visitor2& visitor_; +public: + template + basic_msgpack_reader(Sourceable&& source, + json_visitor& visitor, + const Allocator alloc) + : basic_msgpack_reader(std::forward(source), + visitor, + msgpack_decode_options(), + alloc) + { + } + + template + basic_msgpack_reader(Sourceable&& source, + json_visitor& visitor, + const msgpack_decode_options& options = msgpack_decode_options(), + const Allocator alloc=Allocator()) + : parser_(std::forward(source), options, alloc), + adaptor_(visitor, alloc), visitor_(adaptor_) + { + } + template + basic_msgpack_reader(Sourceable&& source, + json_visitor2& visitor, + const Allocator alloc) + : basic_msgpack_reader(std::forward(source), + visitor, + msgpack_decode_options(), + alloc) + { + } + + template + basic_msgpack_reader(Sourceable&& source, + json_visitor2& visitor, + const msgpack_decode_options& options = msgpack_decode_options(), + const Allocator alloc=Allocator()) + : parser_(std::forward(source), options, alloc), + visitor_(visitor) + { + } + + void read() + { + std::error_code ec; + read(ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec,line(),column())); + } + } + + void read(std::error_code& ec) + { + parser_.reset(); + parser_.parse(visitor_, ec); + if (ec) + { + return; + } + } + + std::size_t line() const + { + return parser_.line(); + } + + std::size_t column() const + { + return parser_.column(); + } +}; + +using msgpack_stream_reader = basic_msgpack_reader; + +using msgpack_bytes_reader = basic_msgpack_reader; + +#if !defined(JSONCONS_NO_DEPRECATED) +JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_reader") typedef msgpack_stream_reader msgpack_reader; +JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_reader") typedef msgpack_bytes_reader msgpack_buffer_reader; +#endif + +}} + +#endif diff --git a/include/jsoncons_ext/msgpack/msgpack_type.hpp b/include/jsoncons_ext/msgpack/msgpack_type.hpp new file mode 100644 index 0000000..aa9f8fd --- /dev/null +++ b/include/jsoncons_ext/msgpack/msgpack_type.hpp @@ -0,0 +1,63 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_MSGPACK_MSGPACK_TYPE_HPP +#define JSONCONS_MSGPACK_MSGPACK_TYPE_HPP + +#include +#include +#include + +namespace jsoncons { namespace msgpack { + + namespace msgpack_type + { + const uint8_t positive_fixint_base_type = 0x00; + const uint8_t nil_type = 0xc0; + const uint8_t false_type = 0xc2; + const uint8_t true_type = 0xc3; + const uint8_t float32_type = 0xca; + const uint8_t float64_type = 0xcb; + const uint8_t uint8_type = 0xcc; + const uint8_t uint16_type = 0xcd; + const uint8_t uint32_type = 0xce; + const uint8_t uint64_type = 0xcf; + const uint8_t int8_type = 0xd0; + const uint8_t int16_type = 0xd1; + const uint8_t int32_type = 0xd2; + const uint8_t int64_type = 0xd3; + + const uint8_t fixmap_base_type = 0x80; + const uint8_t fixarray_base_type = 0x90; + const uint8_t fixstr_base_type = 0xa0; + const uint8_t str8_type = 0xd9; + const uint8_t str16_type = 0xda; + const uint8_t str32_type = 0xdb; + + const uint8_t bin8_type = 0xc4; // 0xC4 + const uint8_t bin16_type = 0xc5; + const uint8_t bin32_type = 0xc6; + + const uint8_t fixext1_type = 0xd4; + const uint8_t fixext2_type = 0xd5; + const uint8_t fixext4_type = 0xd6; + const uint8_t fixext8_type = 0xd7; + const uint8_t fixext16_type = 0xd8; + const uint8_t ext8_type = 0xc7; // 0xC4 + const uint8_t ext16_type = 0xc8; + const uint8_t ext32_type = 0xc9; + + const uint8_t array16_type = 0xdc; + const uint8_t array32_type = 0xdd; + const uint8_t map16_type = 0xde; + const uint8_t map32_type = 0xdf; + const uint8_t negative_fixint_base_type = 0xe0; + } + +} // namespace msgpack +} // namespace jsoncons + +#endif -- cgit v1.2.3