summaryrefslogtreecommitdiffstats
path: root/third_party/msgpack/include/msgpack/v2/unpack.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/msgpack/include/msgpack/v2/unpack.hpp')
-rw-r--r--third_party/msgpack/include/msgpack/v2/unpack.hpp348
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