diff --git a/CMakeLists.txt b/CMakeLists.txt index 5851071f..79d18bc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,6 +183,7 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/adaptor/boost/msgpack_variant_decl.hpp include/msgpack/adaptor/boost/optional.hpp include/msgpack/adaptor/boost/string_ref.hpp + include/msgpack/adaptor/carray.hpp include/msgpack/adaptor/char_ptr.hpp include/msgpack/adaptor/check_container_size.hpp include/msgpack/adaptor/check_container_size_decl.hpp @@ -255,6 +256,7 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/v1/adaptor/boost/msgpack_variant_decl.hpp include/msgpack/v1/adaptor/boost/optional.hpp include/msgpack/v1/adaptor/boost/string_ref.hpp + include/msgpack/v1/adaptor/carray.hpp include/msgpack/v1/adaptor/char_ptr.hpp include/msgpack/v1/adaptor/check_container_size.hpp include/msgpack/v1/adaptor/check_container_size_decl.hpp @@ -331,7 +333,6 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/v1/preprocessor.hpp include/msgpack/v1/sbuffer.hpp include/msgpack/v1/sbuffer_decl.hpp - include/msgpack/v1/type.hpp include/msgpack/v1/unpack.hpp include/msgpack/v1/unpack_decl.hpp include/msgpack/v1/version.hpp diff --git a/include/msgpack/adaptor/carray.hpp b/include/msgpack/adaptor/carray.hpp new file mode 100644 index 00000000..b1caf53d --- /dev/null +++ b/include/msgpack/adaptor/carray.hpp @@ -0,0 +1,15 @@ +// +// MessagePack for C++ static resolution 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_TYPE_CARRAY_HPP +#define MSGPACK_TYPE_CARRAY_HPP + +#include "msgpack/v1/adaptor/carray.hpp" + +#endif // MSGPACK_TYPE_CARRAY_HPP diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index 7ac236ea..e5084a6f 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -1,6 +1,7 @@ #include "cpp_config.hpp" #include "adaptor/array_ref.hpp" #include "adaptor/bool.hpp" +#include "adaptor/carray.hpp" #include "adaptor/char_ptr.hpp" #include "adaptor/deque.hpp" #include "adaptor/ext.hpp" diff --git a/include/msgpack/v1/adaptor/adaptor_base.hpp b/include/msgpack/v1/adaptor/adaptor_base.hpp index 12005244..489362b4 100644 --- a/include/msgpack/v1/adaptor/adaptor_base.hpp +++ b/include/msgpack/v1/adaptor/adaptor_base.hpp @@ -50,27 +50,61 @@ struct object_with_zone { template inline -msgpack::object const& operator>> (msgpack::object const& o, T& v) { +typename msgpack::enable_if< + !is_array::value, + msgpack::object const& +>::type +operator>> (msgpack::object const& o, T& v) { return msgpack::adaptor::convert()(o, v); } +template +inline +msgpack::object const& operator>> (msgpack::object const& o, T(&v)[N]) { + return msgpack::adaptor::convert()(o, v); +} template inline -msgpack::packer& operator<< (msgpack::packer& o, T const& v) { +typename msgpack::enable_if< + !is_array::value, + msgpack::packer& +>::type +operator<< (msgpack::packer& o, T const& v) { return msgpack::adaptor::pack()(o, v); } - -template +template inline -void operator<< (msgpack::object& o, T const& v) { - msgpack::adaptor::object()(o, v); +msgpack::packer& operator<< (msgpack::packer& o, const T(&v)[N]) { + return msgpack::adaptor::pack()(o, v); } template inline -void operator<< (msgpack::object::with_zone& o, T const& v) { +typename msgpack::enable_if< + !is_array::value +>::type +operator<< (msgpack::object& o, T const& v) { + msgpack::adaptor::object()(o, v); +} +template +inline +void operator<< (msgpack::v1::object& o, const T(&v)[N]) { + msgpack::v1::adaptor::object()(o, v); +} + +template +inline +typename msgpack::enable_if< + !is_array::value +>::type +operator<< (msgpack::object::with_zone& o, T const& v) { msgpack::adaptor::object_with_zone()(o, v); } +template +inline +void operator<< (msgpack::object::with_zone& o, const T(&v)[N]) { + msgpack::adaptor::object_with_zone()(o, v); +} /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) diff --git a/include/msgpack/v1/adaptor/adaptor_base_decl.hpp b/include/msgpack/v1/adaptor/adaptor_base_decl.hpp index 13bef574..42e8f0e3 100644 --- a/include/msgpack/v1/adaptor/adaptor_base_decl.hpp +++ b/include/msgpack/v1/adaptor/adaptor_base_decl.hpp @@ -12,6 +12,7 @@ #include "msgpack/versioning.hpp" #include "msgpack/object_fwd.hpp" +#include "msgpack/pack.hpp" namespace msgpack { @@ -43,16 +44,38 @@ struct object_with_zone; // operators template -msgpack::object const& operator>> (msgpack::object const& o, T& v); +typename msgpack::enable_if< + !is_array::value, + msgpack::object const& +>::type +operator>> (msgpack::object const& o, T& v); +template +msgpack::object const& operator>> (msgpack::object const& o, T(&v)[N]); template -msgpack::packer& operator<< (msgpack::packer& o, T const& v); +typename msgpack::enable_if< + !is_array::value, + msgpack::packer& +>::type +operator<< (msgpack::packer& o, T const& v); +template +msgpack::packer& operator<< (msgpack::packer& o, const T(&v)[N]); template -void operator<< (msgpack::object& o, T const& v); +typename msgpack::enable_if< + !is_array::value +>::type +operator<< (msgpack::object& o, T const& v); +template +void operator<< (msgpack::object& o, const T(&v)[N]); template -void operator<< (msgpack::object::with_zone& o, T const& v); +typename msgpack::enable_if< + !is_array::value +>::type +operator<< (msgpack::object::with_zone& o, T const& v); +template +void operator<< (msgpack::object::with_zone& o, const T(&v)[N]); /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) diff --git a/include/msgpack/v1/adaptor/array_ref.hpp b/include/msgpack/v1/adaptor/array_ref.hpp index 36593514..3767c274 100644 --- a/include/msgpack/v1/adaptor/array_ref.hpp +++ b/include/msgpack/v1/adaptor/array_ref.hpp @@ -12,6 +12,7 @@ #include "msgpack/v1/adaptor/array_ref.hpp" #include "msgpack/adaptor/check_container_size.hpp" +#include "msgpack/cpp_config.hpp" #include #include @@ -30,6 +31,10 @@ struct array_ref { T* data; + std::size_t size() const { + return data->size(); + } + template bool operator==(array_ref const& t) const { return *data == *t.data; @@ -60,16 +65,88 @@ struct array_ref { } }; +template +struct array_ref { + array_ref() : data(nullptr) {} + array_ref(T(&t)[N]) : data(t) {} + + T* data; + + std::size_t size() const { + return N; + } + + template + bool operator==(array_ref const& t) const { + if (N != t.size()) return false; + T const* pself = data; + U const* pother = t.data; + for (; pself != &data[N]; ++pself, ++pother) { + if (*pself != *pother) return false; + } + return true; + } + template + bool operator!=(array_ref const& t) const { + return !(*this == t); + } + template + bool operator< (array_ref const& t) const + { + T const* pself = data; + U const* pother = t.data; + for (; pself != &data[N] && pother != t.data[t.size()]; ++pself, ++pother) { + if (*pself < *pother) return true; + } + if (N < t.size()) return true; + return false; + } + template + bool operator> (array_ref const& t) const + { + return t.data < data; + } + template + bool operator<= (array_ref const& t) const + { + return !(t.data < data); + } + template + bool operator>= (array_ref const& t) const + { + return !(data < t.data); + } +}; + template -inline array_ref make_array_ref(T const& t) { +inline +typename msgpack::enable_if< + !msgpack::is_array::value, + array_ref +>::type +make_array_ref(const T& t) { return array_ref(t); } template -inline array_ref make_array_ref(T& t) { +inline +typename msgpack::enable_if< + !msgpack::is_array::value, + array_ref +>::type +make_array_ref(T& t) { return array_ref(t); } +template +inline array_ref make_array_ref(const T(&t)[N]) { + return array_ref(t); +} + +template +inline array_ref make_array_ref(T(&t)[N]) { + return array_ref(t); +} } // namespace type @@ -80,7 +157,7 @@ struct convert > { msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref& v) const { if (!v.data) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } - if (v.data->size() < o.via.bin.size) { throw msgpack::type_error(); } + if (v.size() < o.via.bin.size) { throw msgpack::type_error(); } if (o.via.array.size > 0) { msgpack::object* p = o.via.array.ptr; msgpack::object* const pend = o.via.array.ptr + o.via.array.size; @@ -95,6 +172,26 @@ struct convert > { } }; +template +struct convert > { + msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref& v) const { + if (!v.data) { throw msgpack::type_error(); } + if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } + if (v.size() < o.via.bin.size) { throw msgpack::type_error(); } + if (o.via.array.size > 0) { + msgpack::object* p = o.via.array.ptr; + msgpack::object* const pend = o.via.array.ptr + o.via.array.size; + T* it = v.data; + do { + p->convert(*it); + ++p; + ++it; + } while(p < pend); + } + return o; + } +}; + template struct convert > > { msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref >& v) const { @@ -120,7 +217,7 @@ struct pack > { template msgpack::packer& operator()(msgpack::packer& o, const msgpack::type::array_ref& v) const { if (!v.data) { throw msgpack::type_error(); } - uint32_t size = checked_get_container_size(v.data->size()); + uint32_t size = checked_get_container_size(v.size()); o.pack_array(size); for (typename T::const_iterator it(v.data->begin()), it_end(v.data->end()); it != it_end; ++it) { @@ -130,6 +227,21 @@ struct pack > { } }; +template +struct pack > { + template + msgpack::packer& operator()(msgpack::packer& o, const msgpack::type::array_ref& v) const { + if (!v.data) { throw msgpack::type_error(); } + uint32_t size = checked_get_container_size(v.size()); + o.pack_array(size); + for (T const* it = v.data; + it != &v.data[v.size()]; ++it) { + o.pack(*it); + } + return o; + } +}; + template struct object_with_zone > { void operator()(msgpack::object::with_zone& o, const msgpack::type::array_ref& v) const { @@ -140,7 +252,7 @@ struct object_with_zone > { o.via.array.size = 0; } else { - uint32_t size = checked_get_container_size(v.data->size()); + uint32_t size = checked_get_container_size(v.size()); msgpack::object* p = static_cast(o.zone.allocate_align(sizeof(msgpack::object)*size)); msgpack::object* const pend = p + size; o.via.array.ptr = p; @@ -162,6 +274,26 @@ struct object_with_zone > { } }; +template +struct object_with_zone > { + void operator()(msgpack::object::with_zone& o, const msgpack::type::array_ref& v) const { + if (!v.data) { throw msgpack::type_error(); } + o.type = msgpack::type::ARRAY; + uint32_t size = checked_get_container_size(v.size()); + msgpack::object* p = static_cast(o.zone.allocate_align(sizeof(msgpack::object)*size)); + msgpack::object* const pend = p + size; + o.via.array.ptr = p; + o.via.array.size = size; + T const* it = v.data; + do { + *p = msgpack::object(*it, o.zone); + ++p; + ++it; + } while(p < pend); + } +}; + + } // namespace adaptor /// @cond diff --git a/include/msgpack/v1/adaptor/array_ref_decl.hpp b/include/msgpack/v1/adaptor/array_ref_decl.hpp index 147fd81c..433e24f6 100644 --- a/include/msgpack/v1/adaptor/array_ref_decl.hpp +++ b/include/msgpack/v1/adaptor/array_ref_decl.hpp @@ -25,10 +25,24 @@ template struct array_ref; template -array_ref make_array_ref(T const& t); +typename msgpack::enable_if< + !msgpack::is_array::value, + array_ref +>::type +make_array_ref(T const& t); template -array_ref make_array_ref(T& t); +typename msgpack::enable_if< + !msgpack::is_array::value, + array_ref +>::type +make_array_ref(T& t); + +template +array_ref make_array_ref(const T(&t)[N]); + +template +array_ref make_array_ref(T(&t)[N]); } // namespace type diff --git a/include/msgpack/v1/adaptor/carray.hpp b/include/msgpack/v1/adaptor/carray.hpp new file mode 100644 index 00000000..3d315d7d --- /dev/null +++ b/include/msgpack/v1/adaptor/carray.hpp @@ -0,0 +1,234 @@ +// +// MessagePack for C++ static resolution 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_V1_TYPE_CARRAY_HPP +#define MSGPACK_V1_TYPE_CARRAY_HPP + +#include "msgpack/versioning.hpp" +#include "msgpack/object_fwd.hpp" +#include "msgpack/adaptor/adaptor_base.hpp" +#include "msgpack/adaptor/check_container_size.hpp" + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace adaptor { + +template +struct convert { + msgpack::object const& operator()(msgpack::object const& o, T* v) const { + if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } + if (o.via.array.size > N) { throw msgpack::type_error(); } + msgpack::object* p = o.via.array.ptr; + msgpack::object* const pend = o.via.array.ptr + o.via.array.size; + do { + p->convert(*v); + ++p; + ++v; + } while(p < pend); + return o; + } +}; + +template +struct convert { + msgpack::object const& operator()(msgpack::object const& o, char(&v)[N]) const { + switch (o.type) { + case msgpack::type::BIN: + if (o.via.bin.size > N) { throw msgpack::type_error(); } + std::memcpy(v, o.via.bin.ptr, o.via.bin.size); + break; + case msgpack::type::STR: + if (o.via.str.size + 1 > N) { throw msgpack::type_error(); } + std::memcpy(v, o.via.str.ptr, o.via.str.size); + v[o.via.str.size] = '\0'; + break; + default: + throw msgpack::type_error(); + break; + } + return o; + } +}; + +template +struct convert { + msgpack::object const& operator()(msgpack::object const& o, unsigned char(&v)[N]) const { + switch (o.type) { + case msgpack::type::BIN: + if (o.via.bin.size > N) { throw msgpack::type_error(); } + std::memcpy(v, o.via.bin.ptr, o.via.bin.size); + break; + case msgpack::type::STR: + if (o.via.str.size + 1 > N) { throw msgpack::type_error(); } + std::memcpy(v, o.via.str.ptr, o.via.str.size); + v[o.via.str.size] = '\0'; + break; + default: + throw msgpack::type_error(); + break; + } + return o; + } +}; + + +template +struct pack { + template + msgpack::packer& operator()(msgpack::packer& o, const T(&v)[N]) const { + o.pack_array(N); + const T* ptr = v; + for (; ptr != &v[N]; ++ptr) o.pack(*ptr); + return o; + } +}; + +template +struct pack { + template + msgpack::packer& operator()(msgpack::packer& o, const char(&v)[N]) const { + char const* p = v; + uint32_t size = checked_get_container_size(std::strlen(p)); + o.pack_str(size); + o.pack_str_body(p, size); + return o; + } +}; + +template +struct pack { + template + msgpack::packer& operator()(msgpack::packer& o, const char(&v)[N]) const { + uint32_t size = checked_get_container_size(std::strlen(v)); + o.pack_str(size); + o.pack_str_body(v, size); + return o; + } +}; + +template +struct pack { + template + msgpack::packer& operator()(msgpack::packer& o, const unsigned char(&v)[N]) const { + unsigned char const* p = v; + uint32_t size = checked_get_container_size(N); + o.pack_bin(size); + o.pack_bin_body(reinterpret_cast(p), size); + return o; + } +}; + +template +struct pack { + template + msgpack::packer& operator()(msgpack::packer& o, const unsigned char(&v)[N]) const { + unsigned char const* p = v; + uint32_t size = checked_get_container_size(N); + o.pack_bin(size); + o.pack_bin_body(reinterpret_cast(p), size); + return o; + } +}; + +template +struct object_with_zone { + void operator()(msgpack::object::with_zone& o, const T(&v)[N]) const { + o.type = msgpack::type::ARRAY; + msgpack::object* ptr = static_cast(o.zone.allocate_align(sizeof(msgpack::object) * N)); + o.via.array.ptr = ptr; + o.via.array.size = N; + const T* pv = v; + for (; pv != &v[N]; ++pv) { + *ptr++ = msgpack::object(*pv, o.zone); + } + } +}; + +template +struct object_with_zone { + void operator()(msgpack::object::with_zone& o, const char(&v)[N]) const { + uint32_t size = checked_get_container_size(std::strlen(v)); + o.type = msgpack::type::STR; + char* ptr = static_cast(o.zone.allocate_align(size)); + o.via.str.ptr = ptr; + o.via.str.size = size; + std::memcpy(ptr, v, size); + } +}; + +template +struct object_with_zone { + void operator()(msgpack::object::with_zone& o, const char(&v)[N]) const { + uint32_t size = checked_get_container_size(std::strlen(v)); + o.type = msgpack::type::STR; + char* ptr = static_cast(o.zone.allocate_align(size)); + o.via.str.ptr = ptr; + o.via.str.size = size; + std::memcpy(ptr, v, size); + } +}; + +template +struct object_with_zone { + void operator()(msgpack::object::with_zone& o, const unsigned char(&v)[N]) const { + uint32_t size = checked_get_container_size(N); + o.type = msgpack::type::BIN; + char* ptr = static_cast(o.zone.allocate_align(size)); + o.via.bin.ptr = ptr; + o.via.bin.size = size; + std::memcpy(ptr, v, size); + } +}; + +template +struct object_with_zone { + void operator()(msgpack::object::with_zone& o, const unsigned char(&v)[N]) const { + uint32_t size = checked_get_container_size(N); + o.type = msgpack::type::BIN; + char* ptr = static_cast(o.zone.allocate_align(size)); + o.via.bin.ptr = ptr; + o.via.bin.size = size; + std::memcpy(ptr, v, size); + } +}; + +template +struct object { + void operator()(msgpack::object& o, const char(&v)[N]) const { + uint32_t size = checked_get_container_size(std::strlen(v)); + o.type = msgpack::type::STR; + o.via.str.ptr = v; + o.via.str.size = size; + } +}; + +template +struct object { + void operator()(msgpack::object& o, const char(&v)[N]) const { + uint32_t size = checked_get_container_size(std::strlen(v)); + o.type = msgpack::type::STR; + o.via.str.ptr = v; + o.via.str.size = size; + } +}; + + +} // namespace adaptor + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_V1_TYPE_CARRAY_HPP diff --git a/include/msgpack/v1/adaptor/char_ptr.hpp b/include/msgpack/v1/adaptor/char_ptr.hpp index 760da734..4e6919b8 100644 --- a/include/msgpack/v1/adaptor/char_ptr.hpp +++ b/include/msgpack/v1/adaptor/char_ptr.hpp @@ -81,72 +81,6 @@ struct object { } }; -template -struct pack { - template - msgpack::packer& operator()(msgpack::packer& o, const char* v) const { - uint32_t size = checked_get_container_size(std::strlen(v)); - o.pack_str(size); - o.pack_str_body(v, size); - return o; - } -}; - -template -struct object_with_zone { - void operator()(msgpack::object::with_zone& o, const char* v) const { - uint32_t size = checked_get_container_size(std::strlen(v)); - o.type = msgpack::type::STR; - char* ptr = static_cast(o.zone.allocate_align(size)); - o.via.str.ptr = ptr; - o.via.str.size = size; - std::memcpy(ptr, v, size); - } -}; - -template -struct object { - void operator()(msgpack::object& o, const char* v) const { - uint32_t size = checked_get_container_size(std::strlen(v)); - o.type = msgpack::type::STR; - o.via.str.ptr = v; - o.via.str.size = size; - } -}; - -template -struct pack { - template - msgpack::packer& operator()(msgpack::packer& o, const char* v) const { - uint32_t size = checked_get_container_size(std::strlen(v)); - o.pack_str(size); - o.pack_str_body(v, size); - return o; - } -}; - -template -struct object_with_zone { - void operator()(msgpack::object::with_zone& o, const char* v) const { - uint32_t size = checked_get_container_size(std::strlen(v)); - o.type = msgpack::type::STR; - char* ptr = static_cast(o.zone.allocate_align(size)); - o.via.str.ptr = ptr; - o.via.str.size = size; - std::memcpy(ptr, v, size); - } -}; - -template -struct object { - void operator()(msgpack::object& o, const char* v) const { - uint32_t size = checked_get_container_size(std::strlen(v)); - o.type = msgpack::type::STR; - o.via.str.ptr = v; - o.via.str.size = size; - } -}; - } // namespace adaptor /// @cond diff --git a/include/msgpack/v1/cpp_config.hpp b/include/msgpack/v1/cpp_config.hpp index 09a9004d..e60947ef 100644 --- a/include/msgpack/v1/cpp_config.hpp +++ b/include/msgpack/v1/cpp_config.hpp @@ -70,6 +70,54 @@ struct underlying_type { typedef int type; }; +template +struct is_array : false_type {}; + +template +struct is_array : true_type {}; + +template +struct is_array : true_type {}; + + +template +struct remove_const { + typedef T type; +}; +template +struct remove_const { + typedef T type; +}; + +template +struct remove_volatile { + typedef T type; +}; +template +struct remove_volatile { + typedef T type; +}; + +template +struct remove_cv { + typedef typename msgpack::remove_volatile< + typename msgpack::remove_const::type + >::type type; +}; + +namespace detail { + +template +struct is_pointer_helper : false_type {}; + +template +struct is_pointer_helper : true_type {}; + +} // namespace detail + +template struct is_pointer : detail::is_pointer_helper::type> {}; + + /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) /// @endcond diff --git a/include/msgpack/v1/cpp_config_decl.hpp b/include/msgpack/v1/cpp_config_decl.hpp index 1b35c3ee..c4b05a61 100644 --- a/include/msgpack/v1/cpp_config_decl.hpp +++ b/include/msgpack/v1/cpp_config_decl.hpp @@ -63,6 +63,19 @@ struct is_same; template struct underlying_type; +template +struct is_array; + +template +struct remove_const; +template +struct remove_volatile; +template +struct remove_cv; + +template +struct is_pointer; + /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) /// @endcond @@ -91,6 +104,11 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { using std::enable_if; using std::is_same; using std::underlying_type; + using std::is_array; + using std::remove_const; + using std::remove_volatile; + using std::remove_cv; + using std::is_pointer; /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) diff --git a/include/msgpack/v1/meta_decl.hpp b/include/msgpack/v1/meta_decl.hpp index af5d5858..da403830 100644 --- a/include/msgpack/v1/meta_decl.hpp +++ b/include/msgpack/v1/meta_decl.hpp @@ -38,6 +38,9 @@ template struct seq; template struct gen_seq; +template +struct is_non_const_pointer; + /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) /// @endcond diff --git a/include/msgpack/v1/object.hpp b/include/msgpack/v1/object.hpp index 57721772..01e7bcaf 100644 --- a/include/msgpack/v1/object.hpp +++ b/include/msgpack/v1/object.hpp @@ -526,7 +526,19 @@ inline object::implicit_type object::convert() const } template -inline T& object::convert(T& v) const +inline +typename msgpack::enable_if< + !msgpack::is_array::value && !msgpack::is_pointer::value, + T& +>::type +object::convert(T& v) const +{ + msgpack::operator>>(*this, v); + return v; +} + +template +inline T(&object::convert(T(&v)[N]) const)[N] { msgpack::operator>>(*this, v); return v; @@ -534,7 +546,12 @@ inline T& object::convert(T& v) const #if !defined(MSGPACK_DISABLE_LEGACY_CONVERT) template -inline T* object::convert(T* v) const +inline +typename msgpack::enable_if< + msgpack::is_pointer::value, + T +>::type +object::convert(T v) const { convert(*v); return v; diff --git a/include/msgpack/v1/object_fwd.hpp b/include/msgpack/v1/object_fwd.hpp index 9f6a931f..1af7da09 100644 --- a/include/msgpack/v1/object_fwd.hpp +++ b/include/msgpack/v1/object_fwd.hpp @@ -138,7 +138,14 @@ struct object { * @return The reference of `v`. */ template - T& convert(T& v) const; + typename msgpack::enable_if< + !msgpack::is_array::value && !msgpack::is_pointer::value, + T& + >::type + convert(T& v) const; + + template + T (&convert(T(&v)[N]) const)[N]; #if !defined(MSGPACK_DISABLE_LEGACY_CONVERT) @@ -150,7 +157,11 @@ struct object { * @return The pointer of `v`. */ template - T* convert(T* v) const; + typename msgpack::enable_if< + msgpack::is_pointer::value, + T + >::type + convert(T v) const; #endif // !defined(MSGPACK_DISABLE_LEGACY_CONVERT) /// Convert the object if not nil diff --git a/include/msgpack/v1/type.hpp b/include/msgpack/v1/type.hpp deleted file mode 100644 index 7ac236ea..00000000 --- a/include/msgpack/v1/type.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "cpp_config.hpp" -#include "adaptor/array_ref.hpp" -#include "adaptor/bool.hpp" -#include "adaptor/char_ptr.hpp" -#include "adaptor/deque.hpp" -#include "adaptor/ext.hpp" -#include "adaptor/fixint.hpp" -#include "adaptor/float.hpp" -#include "adaptor/int.hpp" -#include "adaptor/list.hpp" -#include "adaptor/map.hpp" -#include "adaptor/nil.hpp" -#include "adaptor/pair.hpp" -#include "adaptor/raw.hpp" -#include "adaptor/v4raw.hpp" -#include "adaptor/set.hpp" -#include "adaptor/string.hpp" -#include "adaptor/vector.hpp" -#include "adaptor/vector_bool.hpp" -#include "adaptor/vector_char.hpp" -#include "adaptor/vector_unsigned_char.hpp" -#include "adaptor/msgpack_tuple.hpp" -#include "adaptor/define.hpp" - -#if defined(MSGPACK_USE_CPP03) - -#include "adaptor/tr1/unordered_map.hpp" -#include "adaptor/tr1/unordered_set.hpp" - -#else // defined(MSGPACK_USE_CPP03) - -#include "adaptor/cpp11/array.hpp" -#include "adaptor/cpp11/array_char.hpp" -#include "adaptor/cpp11/array_unsigned_char.hpp" -#include "adaptor/cpp11/forward_list.hpp" -#include "adaptor/cpp11/reference_wrapper.hpp" -#include "adaptor/cpp11/shared_ptr.hpp" -#include "adaptor/cpp11/tuple.hpp" -#include "adaptor/cpp11/unique_ptr.hpp" -#include "adaptor/cpp11/unordered_map.hpp" -#include "adaptor/cpp11/unordered_set.hpp" - -#endif // defined(MSGPACK_USE_CPP03) - -#if defined(MSGPACK_USE_BOOST) - -#include "adaptor/boost/fusion.hpp" -#include "adaptor/boost/msgpack_variant.hpp" -#include "adaptor/boost/optional.hpp" -#include "adaptor/boost/string_ref.hpp" - -#endif // defined(MSGPACK_USE_BOOST) diff --git a/include/msgpack/v2/adaptor/adaptor_base.hpp b/include/msgpack/v2/adaptor/adaptor_base.hpp index 154bf1c6..74d591c9 100644 --- a/include/msgpack/v2/adaptor/adaptor_base.hpp +++ b/include/msgpack/v2/adaptor/adaptor_base.hpp @@ -32,7 +32,14 @@ struct pack : v1::adaptor::pack { }; template -struct object::value>::type> : v1::adaptor::object { +struct object< + T, + Enabler, + typename msgpack::enable_if< + !msgpack::is_same::value && + !msgpack::is_array::value + >::type> + : v1::adaptor::object { }; template diff --git a/include/msgpack/v2/cpp_config_decl.hpp b/include/msgpack/v2/cpp_config_decl.hpp index 7e9219cc..7e2e9832 100644 --- a/include/msgpack/v2/cpp_config_decl.hpp +++ b/include/msgpack/v2/cpp_config_decl.hpp @@ -32,6 +32,14 @@ using v1::is_same; using v1::underlying_type; +using v1::is_array; + +using v1::remove_const; +using v1::remove_volatile; +using v1::remove_cv; + +using v1::is_pointer; + /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v2) /// @endcond @@ -57,6 +65,13 @@ using v1::swap; using v1::enable_if; using v1::is_same; using v1::underlying_type; +using v1::is_array; + +using v1::remove_const; +using v1::remove_volatile; +using v1::remove_cv; + +using v1::is_pointer; /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v2) diff --git a/src/Makefile.am b/src/Makefile.am index f4510079..21b866f7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -172,6 +172,7 @@ nobase_include_HEADERS += \ ../include/msgpack/adaptor/boost/msgpack_variant_decl.hpp \ ../include/msgpack/adaptor/boost/optional.hpp \ ../include/msgpack/adaptor/boost/string_ref.hpp \ + ../include/msgpack/adaptor/carray.hpp \ ../include/msgpack/adaptor/char_ptr.hpp \ ../include/msgpack/adaptor/check_container_size.hpp \ ../include/msgpack/adaptor/check_container_size_decl.hpp \ @@ -244,6 +245,7 @@ nobase_include_HEADERS += \ ../include/msgpack/v1/adaptor/boost/msgpack_variant_decl.hpp \ ../include/msgpack/v1/adaptor/boost/optional.hpp \ ../include/msgpack/v1/adaptor/boost/string_ref.hpp \ + ../include/msgpack/v1/adaptor/carray.hpp \ ../include/msgpack/v1/adaptor/char_ptr.hpp \ ../include/msgpack/v1/adaptor/check_container_size.hpp \ ../include/msgpack/v1/adaptor/check_container_size_decl.hpp \ @@ -320,7 +322,6 @@ nobase_include_HEADERS += \ ../include/msgpack/v1/preprocessor.hpp \ ../include/msgpack/v1/sbuffer.hpp \ ../include/msgpack/v1/sbuffer_decl.hpp \ - ../include/msgpack/v1/type.hpp \ ../include/msgpack/v1/unpack.hpp \ ../include/msgpack/v1/unpack_decl.hpp \ ../include/msgpack/v1/version.hpp \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5dfbbe44..854e16a3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,6 +10,7 @@ INCLUDE_DIRECTORIES ( LIST (APPEND check_PROGRAMS array_ref.cpp buffer.cpp + carray.cpp cases.cpp convert.cpp fixint.cpp diff --git a/test/Makefile.am b/test/Makefile.am index 5f451d02..fed1bd2f 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -5,6 +5,7 @@ AM_LDFLAGS = $(top_builddir)/src/libmsgpackc.la -lgtest_main -lgtest -lpthread check_PROGRAMS = \ array_ref \ buffer \ + carray \ cases \ convert \ fixint \ @@ -50,6 +51,7 @@ TESTS = $(check_PROGRAMS) array_ref_SOURCES = array_ref.cpp buffer_SOURCES = buffer.cpp +carray_SOURCES = carray.cpp cases_SOURCES = cases.cpp convert_SOURCES = convert.cpp fixint_SOURCES = fixint.cpp diff --git a/test/carray.cpp b/test/carray.cpp new file mode 100644 index 00000000..56b874f4 --- /dev/null +++ b/test/carray.cpp @@ -0,0 +1,264 @@ +#include +#include +#include + +TEST(carray, pack_unpack_int) +{ + std::stringstream ss; + int v1[] = { 0, 1 }; + + msgpack::pack(ss, v1); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + + int v2[2]; + oh.get().convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_int) +{ + int v1[] = { 0, 1 }; + msgpack::zone z; + + msgpack::object o(v1, z); + EXPECT_EQ(o.type, msgpack::type::ARRAY); + + int v2[2]; + o.convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, pack_unpack_const_int) +{ + std::stringstream ss; + const int v1[] = { 0, 1 }; + + msgpack::pack(ss, v1); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + + int v2[2]; + oh.get().convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_const_int) +{ + const int v1[] = { 0, 1 }; + msgpack::zone z; + + msgpack::object o(v1, z); + EXPECT_EQ(o.type, msgpack::type::ARRAY); + + int v2[2]; + o.convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, pack_unpack_string) +{ + std::stringstream ss; + std::string v1[] = { "ABC", "DEFG" }; + + msgpack::pack(ss, v1); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + + std::string v2[2]; + oh.get().convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_string) +{ + std::string v1[] = { "ABC", "DEFG" }; + msgpack::zone z; + + msgpack::object o(v1, z); + EXPECT_EQ(o.type, msgpack::type::ARRAY); + + std::string v2[2]; + o.convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, pack_unpack_char) +{ + std::stringstream ss; + char v1[] = { 0, 1 }; + + msgpack::pack(ss, msgpack::type::make_array_ref(v1)); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + + char v2[2]; + msgpack::type::array_ref ar = msgpack::type::make_array_ref(v2); + oh.get().convert(ar); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, pack_unpack_char_as_str) +{ + std::stringstream ss; + char v1[2] = { 1, '\0' }; + + msgpack::pack(ss, v1); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::STR); + EXPECT_EQ(oh.get().via.str.size, 1); + + char v2[2] = { 2, 3 }; + oh.get().convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_char) +{ + char v1[] = { 0, 1 }; + msgpack::zone z; + + msgpack::object o(msgpack::type::make_array_ref(v1), z); + EXPECT_EQ(o.type, msgpack::type::ARRAY); + + char v2[2]; + msgpack::type::array_ref ar = msgpack::type::make_array_ref(v2); + o.convert(ar); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_char_as_str) +{ + char v1[] = { 1, '\0' }; + msgpack::zone z; + + msgpack::object o(v1, z); + EXPECT_EQ(o.type, msgpack::type::STR); + EXPECT_EQ(o.via.str.size, 1); + + char v2[2]; + o.convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, pack_unpack_unsigned_char) +{ + std::stringstream ss; + unsigned char v1[] = { 0, 1 }; + + msgpack::pack(ss, msgpack::type::make_array_ref(v1)); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + + unsigned char v2[2]; + msgpack::type::array_ref ar = msgpack::type::make_array_ref(v2); + oh.get().convert(ar); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, pack_unpack_unsigned_char_as_bin) +{ + std::stringstream ss; + unsigned char v1[] = { 0, 1 }; + + msgpack::pack(ss, v1); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::BIN); + EXPECT_EQ(oh.get().via.bin.size, 2); + + unsigned char v2[2]; + oh.get().convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_unsigned_char) +{ + unsigned char v1[] = { 0, 1 }; + msgpack::zone z; + + msgpack::object o(msgpack::type::make_array_ref(v1), z); + EXPECT_EQ(o.type, msgpack::type::ARRAY); + + unsigned char v2[2]; + msgpack::type::array_ref ar = msgpack::type::make_array_ref(v2); + o.convert(ar); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_unsigned_char_as_bin) +{ + unsigned char v1[] = { 0, 1 }; + msgpack::zone z; + + msgpack::object o(v1, z); + EXPECT_EQ(o.type, msgpack::type::BIN); + EXPECT_EQ(o.via.bin.size, 2); + + unsigned char v2[2]; + o.convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, pack_unpack_signed_char) +{ + std::stringstream ss; + signed char v1[] = { 0, 1 }; + + msgpack::pack(ss, v1); + msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); + EXPECT_EQ(oh.get().type, msgpack::type::ARRAY); + + signed char v2[2]; + oh.get().convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +TEST(carray, obj_with_zone_signed_char) +{ + signed char v1[] = { 0, 1 }; + msgpack::zone z; + + msgpack::object o(v1, z); + EXPECT_EQ(o.type, msgpack::type::ARRAY); + + signed char v2[2]; + o.convert(v2); + EXPECT_EQ(v1[0], v2[0]); + EXPECT_EQ(v1[1], v2[1]); +} + +#if MSGPACK_DEFAULT_API_VERSION == 1 + +TEST(carray, object_as_str) +{ + char v1[] = { 1, '\0' }; + + msgpack::zone z; + msgpack::object o(v1); + EXPECT_EQ(o.type, msgpack::type::STR); +} +TEST(carray, object_as_str_const) +{ + const char v1[] = { 1, '\0' }; + + msgpack::zone z; + msgpack::object o(v1); + EXPECT_EQ(o.type, msgpack::type::STR); +} + +#endif // MSGPACK_DEFAULT_API_VERSION == 1 diff --git a/test/object_with_zone.cpp b/test/object_with_zone.cpp index eab3ac8b..c28a60ff 100644 --- a/test/object_with_zone.cpp +++ b/test/object_with_zone.cpp @@ -341,6 +341,8 @@ TEST(object_with_zone, char_ptr) EXPECT_EQ(obj.as()[0], 'a'); } +#if MSGPACK_DEFAULT_API_VERSION == 1 + TEST(object_without_zone, char_ptr) { char v[] = "abc"; @@ -351,6 +353,7 @@ TEST(object_without_zone, char_ptr) EXPECT_EQ(obj.as()[0], 'd'); } +#endif // MSGPACK_DEFAULT_API_VERSION == 1 // raw_ref TEST(object_with_zone, raw_ref)