diff options
Diffstat (limited to 'third_party/msgpack/include/msgpack/v2/unpack.hpp')
-rw-r--r-- | third_party/msgpack/include/msgpack/v2/unpack.hpp | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/third_party/msgpack/include/msgpack/v2/unpack.hpp b/third_party/msgpack/include/msgpack/v2/unpack.hpp new file mode 100644 index 0000000000..993643ab07 --- /dev/null +++ b/third_party/msgpack/include/msgpack/v2/unpack.hpp @@ -0,0 +1,348 @@ +// +// MessagePack for C++ deserializing routine +// +// Copyright (C) 2016 KONDO Takatoshi +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef MSGPACK_V2_UNPACK_HPP +#define MSGPACK_V2_UNPACK_HPP + +#if MSGPACK_DEFAULT_API_VERSION >= 2 + +#include "msgpack/unpack_decl.hpp" +#include "msgpack/parse.hpp" +#include "msgpack/create_object_visitor.hpp" + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v2) { +/// @endcond + + +struct zone_push_finalizer { + zone_push_finalizer(msgpack::zone& z):m_z(&z) {} + void set_zone(msgpack::zone& z) { m_z = &z; } + void operator()(char* buffer) { + m_z->push_finalizer(&detail::decr_count, buffer); + } + msgpack::zone* m_z; +}; + +class unpacker : public parser<unpacker, zone_push_finalizer>, + public detail::create_object_visitor { + typedef parser<unpacker, zone_push_finalizer> parser_t; +public: + unpacker(unpack_reference_func f = &unpacker::default_reference_func, + void* user_data = MSGPACK_NULLPTR, + std::size_t initial_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE, + unpack_limit const& limit = unpack_limit()) + :parser_t(m_finalizer, initial_buffer_size), + detail::create_object_visitor(f, user_data, limit), + m_z(new msgpack::zone), + m_finalizer(*m_z) { + set_zone(*m_z); + set_referenced(false); + } + + detail::create_object_visitor& visitor() { return *this; } + /// Unpack one msgpack::object. + /** + * + * @param result The object that contains unpacked data. + * @param referenced If the unpacked object contains reference of the buffer, + * then set as true, otherwise false. + * + * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete + * and additional data is required, then return false. If data format is invalid, throw + * msgpack::parse_error. + * + * See: + * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer + */ + bool next(msgpack::object_handle& result, bool& referenced); + + /// Unpack one msgpack::object. + /** + * + * @param result The object that contains unpacked data. + * + * @return If one msgpack::object is unpacked, then return true, if msgpack::object is incomplete + * and additional data is required, then return false. If data format is invalid, throw + * msgpack::parse_error. + * + * See: + * https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_unpacker#msgpack-controls-a-buffer + */ + bool next(msgpack::object_handle& result); + msgpack::zone* release_zone(); + void reset_zone(); + bool flush_zone(); +private: + static bool default_reference_func(msgpack::type::object_type /*type*/, std::size_t /*len*/, void*) { + return true; + } + msgpack::unique_ptr<msgpack::zone> m_z; + zone_push_finalizer m_finalizer; +}; + +inline bool unpacker::next(msgpack::object_handle& result, bool& referenced) { + bool ret = parser_t::next(); + if (ret) { + referenced = detail::create_object_visitor::referenced(); + result.zone().reset( release_zone() ); + result.set(data()); + reset(); + } + else { + result.zone().reset(); + result.set(msgpack::object()); + } + return ret; +} + +inline bool unpacker::next(msgpack::object_handle& result) { + bool referenced; + return next(result, referenced); +} + +inline msgpack::zone* unpacker::release_zone() +{ + if(!flush_zone()) { + return MSGPACK_NULLPTR; + } + + msgpack::zone* r = new msgpack::zone; + msgpack::zone* old = m_z.release(); + m_z.reset(r); + set_zone(*m_z); + m_finalizer.set_zone(*m_z); + + return old; +} + +inline void unpacker::reset_zone() +{ + m_z->clear(); +} + +inline bool unpacker::flush_zone() +{ + if(referenced()) { + try { + m_z->push_finalizer(&detail::decr_count, get_raw_buffer()); + } catch (...) { + return false; + } + set_referenced(false); + + detail::incr_count(get_raw_buffer()); + } + + return true; +} + +inline msgpack::object_handle unpack( + const char* data, std::size_t len, std::size_t& off, bool& referenced, + unpack_reference_func f, void* user_data, + unpack_limit const& limit +) +{ + msgpack::object obj; + msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone); + referenced = false; + std::size_t noff = off; + parse_return ret = detail::unpack_imp( + data, len, noff, *z, obj, referenced, f, user_data, limit); + + switch(ret) { + case PARSE_SUCCESS: + off = noff; + return msgpack::object_handle(obj, msgpack::move(z)); + case PARSE_EXTRA_BYTES: + off = noff; + return msgpack::object_handle(obj, msgpack::move(z)); + default: + break; + } + return msgpack::object_handle(); +} + +inline msgpack::object_handle unpack( + const char* data, std::size_t len, std::size_t& off, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + bool referenced; + return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit); +} + +inline msgpack::object_handle unpack( + const char* data, std::size_t len, bool& referenced, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + std::size_t off = 0; + return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit); +} + +inline msgpack::object_handle unpack( + const char* data, std::size_t len, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + bool referenced; + std::size_t off = 0; + return msgpack::v2::unpack(data, len, off, referenced, f, user_data, limit); +} + +inline void unpack( + msgpack::object_handle& result, + const char* data, std::size_t len, std::size_t& off, bool& referenced, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + msgpack::object obj; + msgpack::unique_ptr<msgpack::zone> z(new msgpack::zone); + referenced = false; + std::size_t noff = off; + parse_return ret = detail::unpack_imp( + data, len, noff, *z, obj, referenced, f, user_data, limit); + + switch(ret) { + case PARSE_SUCCESS: + off = noff; + result.set(obj); + result.zone() = msgpack::move(z); + return; + case PARSE_EXTRA_BYTES: + off = noff; + result.set(obj); + result.zone() = msgpack::move(z); + return; + default: + return; + } +} + +inline void unpack( + msgpack::object_handle& result, + const char* data, std::size_t len, std::size_t& off, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + bool referenced; + msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit); +} + +inline void unpack( + msgpack::object_handle& result, + const char* data, std::size_t len, bool& referenced, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + std::size_t off = 0; + msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit); +} + +inline void unpack( + msgpack::object_handle& result, + const char* data, std::size_t len, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + bool referenced; + std::size_t off = 0; + msgpack::v2::unpack(result, data, len, off, referenced, f, user_data, limit); +} + + +inline msgpack::object unpack( + msgpack::zone& z, + const char* data, std::size_t len, std::size_t& off, bool& referenced, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + msgpack::object obj; + std::size_t noff = off; + referenced = false; + parse_return ret = detail::unpack_imp( + data, len, noff, z, obj, referenced, f, user_data, limit); + + switch(ret) { + case PARSE_SUCCESS: + off = noff; + return obj; + case PARSE_EXTRA_BYTES: + off = noff; + return obj; + default: + break; + } + return obj; +} + +inline msgpack::object unpack( + msgpack::zone& z, + const char* data, std::size_t len, std::size_t& off, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + bool referenced; + return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit); +} + +inline msgpack::object unpack( + msgpack::zone& z, + const char* data, std::size_t len, bool& referenced, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + std::size_t off = 0; + return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit); +} + +inline msgpack::object unpack( + msgpack::zone& z, + const char* data, std::size_t len, + unpack_reference_func f, void* user_data, + unpack_limit const& limit) +{ + bool referenced; + std::size_t off = 0; + return msgpack::v2::unpack(z, data, len, off, referenced, f, user_data, limit); +} + +namespace detail { + +inline parse_return +unpack_imp(const char* data, std::size_t len, std::size_t& off, + msgpack::zone& result_zone, msgpack::object& result, bool& referenced, + unpack_reference_func f = MSGPACK_NULLPTR, void* user_data = MSGPACK_NULLPTR, + unpack_limit const& limit = unpack_limit()) +{ + create_object_visitor v(f, user_data, limit); + v.set_zone(result_zone); + referenced = false; + v.set_referenced(referenced); + parse_return ret = parse_imp(data, len, off, v); + referenced = v.referenced(); + result = v.data(); + return ret; +} + +} // namespace detail + + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v2) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_DEFAULT_API_VERSION >= 2 + +#endif // MSGPACK_V2_UNPACK_HPP |