diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b91fb7d..3e92db3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,6 +166,7 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack/adaptor/adaptor_base.hpp include/msgpack/adaptor/bool.hpp include/msgpack/adaptor/boost/fusion.hpp + include/msgpack/adaptor/boost/msgpack_variant.hpp include/msgpack/adaptor/boost/optional.hpp include/msgpack/adaptor/boost/string_ref.hpp include/msgpack/adaptor/char_ptr.hpp diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 5fa8a3f6..e447d1a2 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,3 +1,4 @@ ADD_SUBDIRECTORY (c) ADD_SUBDIRECTORY (cpp03) ADD_SUBDIRECTORY (cpp11) +ADD_SUBDIRECTORY (boost) diff --git a/example/boost/CMakeLists.txt b/example/boost/CMakeLists.txt new file mode 100644 index 00000000..57a31acc --- /dev/null +++ b/example/boost/CMakeLists.txt @@ -0,0 +1,24 @@ +IF (MSGPACK_BOOST) + LIST (APPEND exec_PROGRAMS + msgpack_variant_capitalize.cpp + msgpack_variant_mapbased.cpp + ) +ENDIF () + +FOREACH (source_file ${exec_PROGRAMS}) + GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE) + ADD_EXECUTABLE ( + ${source_file_we} + ${source_file} + ) + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -Wno-mismatched-tags -g -O3") + ENDIF () + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + ELSE () + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX") + ENDIF () + ENDIF () +ENDFOREACH () diff --git a/example/boost/msgpack_variant_capitalize.cpp b/example/boost/msgpack_variant_capitalize.cpp new file mode 100644 index 00000000..317e7ac0 --- /dev/null +++ b/example/boost/msgpack_variant_capitalize.cpp @@ -0,0 +1,102 @@ +// MessagePack for C++ example +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include +#include +#include +#include +#include + +#include + +struct user { + std::string name; + int age; + std::string address; + MSGPACK_DEFINE(name, age, address); +}; + +struct proc:boost::static_visitor { + void operator()(std::string& v) const { + std::cout << " match std::string& v" << std::endl; + std::cout << " v: " << v << std::endl; + std::cout << " capitalize" << std::endl; + for (std::string::iterator it = v.begin(), end = v.end(); + it != end; + ++it) { + *it = std::toupper(*it); + } + } + void operator()(std::vector& v) const { + std::cout << "match vector (msgpack::type::ARRAY)" << std::endl; + std::vector::iterator it = v.begin(); + std::vector::const_iterator end = v.end(); + for (; it != end; ++it) { + boost::apply_visitor(*this, *it); + } + } + template + void operator()(T const&) const { + std::cout << " match others" << std::endl; + } +}; + +void print(std::string const& buf) { + for (std::string::const_iterator it = buf.begin(), end = buf.end(); + it != end; + ++it) { + std::cout + << std::setw(2) + << std::hex + << std::setfill('0') + << (static_cast(*it) & 0xff) + << ' '; + } + std::cout << std::dec << std::endl; +} + + +int main() { + std::stringstream ss1; + user u; + u.name = "Takatoshi Kondo"; + u.age = 42; + u.address = "Tokyo, JAPAN"; + + std::cout << "Packing object." << std::endl; + msgpack::pack(ss1, u); + print(ss1.str()); + + msgpack::unpacked unp1 = msgpack::unpack(ss1.str().data(), ss1.str().size()); + msgpack::object const& obj1 = unp1.get(); + std::cout << "Unpacked msgpack object." << std::endl; + std::cout << obj1 << std::endl; + + msgpack::type::variant v = obj1.as(); + std::cout << "Applying proc..." << std::endl; + boost::apply_visitor(proc(), v); + + std::stringstream ss2; + std::cout << "Packing modified object." << std::endl; + msgpack::pack(ss2, v); + print(ss2.str()); + + msgpack::unpacked unp2 = msgpack::unpack(ss2.str().data(), ss2.str().size()); + msgpack::object const& obj2 = unp2.get(); + std::cout << "Modified msgpack object." << std::endl; + std::cout << obj2 << std::endl; +} diff --git a/example/boost/msgpack_variant_mapbased.cpp b/example/boost/msgpack_variant_mapbased.cpp new file mode 100644 index 00000000..9c4150b0 --- /dev/null +++ b/example/boost/msgpack_variant_mapbased.cpp @@ -0,0 +1,95 @@ +// MessagePack for C++ example +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include +#include +#include + +#include + +struct user { + std::string name; + int age; + std::string address; + MSGPACK_DEFINE_MAP(name, age, address); +}; + +struct proc:boost::static_visitor { + // msgpack::type::MAP is converted to std::multimap, not std::map. + void operator()(std::multimap& v) const { + std::cout << "match map" << std::endl; + std::multimap::iterator it = v.begin(); + std::multimap::iterator end = v.end(); + while(it != end) { + boost::string_ref const& key = boost::get(it->first); + if (key == "name") { + boost::string_ref const& value = boost::get(it->second); + if (value == "Takatoshi Kondo") { + // You can add values to msgpack::type::variant_ref. + v.insert( + std::multimap::value_type( + std::string("role"), + std::string("msgpack-c committer") + ) + ); + } + ++it; + } + else if (key == "age") { + // You can remove key-value pair from msgpack::type::variant_ref +#if defined(MSGPACK_USE_CPP03) + v.erase(it++); +#else + it = v.erase(it); +#endif + } + else if (key == "address") { + // When you want to append string + // "Tokyo" -> "Tokyo, JAPAN" + // Use msgpack::type::variant instead of msgpack::type::varinat_ref + // or do as follows: + boost::string_ref const& value = boost::get(it->second); + it->second = std::string(&value.front(), value.size()) + ", JAPAN"; + ++it; + } + } + } + template + void operator()(T const&) const { + std::cout << " match others" << std::endl; + } +}; + +int main() { + std::stringstream ss; + user u; + u.name = "Takatoshi Kondo"; + u.age = 42; + u.address = "Tokyo"; + msgpack::pack(ss, u); + + msgpack::unpacked unp = msgpack::unpack(ss.str().data(), ss.str().size()); + msgpack::object const& obj = unp.get(); + std::cout << "Unpacked msgpack object." << std::endl; + std::cout << obj << std::endl; + msgpack::type::variant_ref v = obj.as(); + std::cout << "Applying proc..." << std::endl; + boost::apply_visitor(proc(), v); + msgpack::zone z; + std::cout << "Applied msgpack object." << std::endl; + std::cout << msgpack::object(v, z) << std::endl; +} diff --git a/include/msgpack/adaptor/boost/msgpack_variant.hpp b/include/msgpack/adaptor/boost/msgpack_variant.hpp new file mode 100644 index 00000000..07a75392 --- /dev/null +++ b/include/msgpack/adaptor/boost/msgpack_variant.hpp @@ -0,0 +1,391 @@ +// +// MessagePack for C++ static resolution routine +// +// Copyright (C) 2015 KONDO Takatoshi +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef MSGPACK_TYPE_BOOST_MSGPACK_VARIANT_HPP +#define MSGPACK_TYPE_BOOST_MSGPACK_VARIANT_HPP + +#if defined(MSGPACK_USE_BOOST) + +#include "msgpack/versioning.hpp" +#include "msgpack/adaptor/adaptor_base.hpp" +#include "msgpack/adaptor/check_container_size.hpp" +#include "msgpack/adaptor/boost/string_ref.hpp" + +#include "msgpack/adaptor/nil.hpp" +#include "msgpack/adaptor/bool.hpp" +#include "msgpack/adaptor/int.hpp" +#include "msgpack/adaptor/float.hpp" +#include "msgpack/adaptor/string.hpp" +#include "msgpack/adaptor/vector_char.hpp" +#include "msgpack/adaptor/raw.hpp" +#include "msgpack/adaptor/ext.hpp" +#include "msgpack/adaptor/vector.hpp" +#include "msgpack/adaptor/map.hpp" + +#include + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace type { + +typedef boost::make_recursive_variant< + nil, // NIL + bool, // BOOL + int64_t, // NEGATIVE_INTEGER + uint64_t, // POSITIVE_INTEGER + double, // FLOAT + std::string, // STR +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + boost::string_ref, // STR +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + std::vector, // BIN + msgpack::type::raw_ref, // BIN + ext, // EXT + ext_ref, // EXT + std::vector, // ARRAY + std::map, // MAP + std::multimap // MAP +>::type variant; + +namespace detail { +struct ref_tag { +#if defined(MSGPACK_USE_CPP03) +private: + ref_tag(); +#else // defined(MSGPACK_USE_CPP03) + ref_tag() = delete; +#endif // defined(MSGPACK_USE_CPP03) +public: + MSGPACK_DEFINE(); +}; + +inline bool operator<(ref_tag const& lhs, ref_tag const& rhs) { + return &lhs < &rhs; +} +inline bool operator==(ref_tag const& lhs, ref_tag const& rhs) { + return &lhs == &rhs; +} +} // namespace detail + +typedef boost::make_recursive_variant< + nil, // NIL + bool, // BOOL + int64_t, // NEGATIVE_INTEGER + uint64_t, // POSITIVE_INTEGER + double, // FLOAT + std::string, // STR +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + boost::string_ref, // STR +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + std::vector, // BIN + msgpack::type::raw_ref, // BIN + ext, // EXT + ext_ref, // EXT + std::vector, // ARRAY + std::map, // MAP + std::multimap, // MAP + detail::ref_tag +>::type variant_ref; + +} // namespace type + + + + +namespace adaptor { + +#if !defined (MSGPACK_USE_CPP03) + +template <> +struct as { + msgpack::type::variant operator()(msgpack::object const& o) const { + switch(o.type) { + case type::NIL: + return o.as(); + case type::BOOLEAN: + return o.as(); + case type::POSITIVE_INTEGER: + return o.as(); + case type::NEGATIVE_INTEGER: + return o.as(); + case type::FLOAT: + return o.as(); + case type::STR: + return o.as(); + case type::BIN: + return o.as >(); + case type::EXT: + return o.as(); + case type::ARRAY: + return o.as >(); + case type::MAP: + return o.as >(); + default: + break; + } + return msgpack::type::variant(); + } +}; + +#endif // !defined (MSGPACK_USE_CPP03) + + +template <> +struct convert { + msgpack::object const& operator()( + msgpack::object const& o, + msgpack::type::variant& v) const { + switch(o.type) { + case type::NIL: + v = o.as(); + break; + case type::BOOLEAN: + v = o.as(); + break; + case type::POSITIVE_INTEGER: + v = o.as(); + break; + case type::NEGATIVE_INTEGER: + v = o.as(); + break; + case type::FLOAT: + v = o.as(); + break; + case type::STR: + v = o.as(); + break; + case type::BIN: + v = o.as >(); + break; + case type::EXT: + v = o.as(); + break; + case type::ARRAY: + v = o.as >(); + break; + case type::MAP: + v = o.as >(); + break; + default: + break; + } + return o; + } +}; + +namespace detail { + +template +struct pack_imp:boost::static_visitor { + template + void operator()(T const& value) const { + pack()(o_, value); + } + pack_imp(packer& o):o_(o) {} + packer& o_; +}; + +} // namespace detail + +template <> +struct pack { + template + msgpack::packer& operator()(msgpack::packer& o, const msgpack::type::variant& v) const { + boost::apply_visitor(detail::pack_imp(o), v); + return o; + } +}; + +namespace detail { + +struct object_imp:boost::static_visitor { + void operator()(msgpack::type::nil const& v) const { + object()(o_, v); + } + void operator()(bool const& v) const { + object()(o_, v); + } + void operator()(uint64_t const& v) const { + object()(o_, v); + } + void operator()(int64_t const& v) const { + object()(o_, v); + } + void operator()(double const& v) const { + object()(o_, v); + } + template + void operator()(T const&) const { + throw msgpack::type_error(); + } + object_imp(msgpack::object& o):o_(o) {} + msgpack::object& o_; +}; + +} // namespace detail + +template <> +struct object { + void operator()(msgpack::object& o, const msgpack::type::variant& v) const { + boost::apply_visitor(detail::object_imp(o), v); + } +}; + +namespace detail { + +struct object_with_zone_imp:boost::static_visitor { + template + void operator()(T const& v) const { + object_with_zone()(o_, v); + } + object_with_zone_imp(msgpack::object::with_zone& o):o_(o) {} + msgpack::object::with_zone& o_; +}; + +} // namespace detail + +template <> +struct object_with_zone { + void operator()(msgpack::object::with_zone& o, const msgpack::type::variant& v) const { + boost::apply_visitor(detail::object_with_zone_imp(o), v); + } +}; + +#if !defined (MSGPACK_USE_CPP03) + +template <> +struct as { + msgpack::type::variant_ref operator()(msgpack::object const& o) const { + switch(o.type) { + case type::NIL: + return o.as(); + case type::BOOLEAN: + return o.as(); + case type::POSITIVE_INTEGER: + return o.as(); + case type::NEGATIVE_INTEGER: + return o.as(); + case type::FLOAT: + return o.as(); + case type::STR: +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + return o.as(); +#else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + return o.as(); +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + case type::BIN: + return o.as(); + case type::EXT: + return o.as(); + case type::ARRAY: + return o.as >(); + case type::MAP: + return o.as >(); + default: + break; + } + return msgpack::type::variant_ref(); + } +}; + +#endif // !defined (MSGPACK_USE_CPP03) + + +template <> +struct convert { + msgpack::object const& operator()( + msgpack::object const& o, + msgpack::type::variant_ref& v) const { + switch(o.type) { + case type::NIL: + v = o.as(); + break; + case type::BOOLEAN: + v = o.as(); + break; + case type::POSITIVE_INTEGER: + v = o.as(); + break; + case type::NEGATIVE_INTEGER: + v = o.as(); + break; + case type::FLOAT: + v = o.as(); + break; + case type::STR: +#if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v = o.as(); +#else // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + v = o.as(); +#endif // (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 53 + break; + case type::BIN: + v = o.as(); + break; + case type::EXT: + v = o.as(); + break; + case type::ARRAY: + v = o.as >(); + break; + case type::MAP: + v = o.as >(); + break; + default: + break; + } + return o; + } +}; + +template <> +struct pack { + template + msgpack::packer& operator()(msgpack::packer& o, const msgpack::type::variant_ref& v) const { + boost::apply_visitor(detail::pack_imp(o), v); + return o; + } +}; + +template <> +struct object { + void operator()(msgpack::object& o, const msgpack::type::variant_ref& v) const { + boost::apply_visitor(detail::object_imp(o), v); + } +}; + +template <> +struct object_with_zone { + void operator()(msgpack::object::with_zone& o, const msgpack::type::variant_ref& v) const { + boost::apply_visitor(detail::object_with_zone_imp(o), v); + } +}; + +} // namespace adaptor + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_USE_BOOST +#endif // MSGPACK_TYPE_BOOST_MSGPACK_VARIANT_HPP diff --git a/include/msgpack/adaptor/nil.hpp b/include/msgpack/adaptor/nil.hpp index 2f99f1ad..607f767a 100644 --- a/include/msgpack/adaptor/nil.hpp +++ b/include/msgpack/adaptor/nil.hpp @@ -31,6 +31,14 @@ namespace type { struct nil { }; +inline bool operator<(nil const& lhs, nil const& rhs) { + return &lhs < &rhs; +} + +inline bool operator==(nil const& lhs, nil const& rhs) { + return &lhs == &rhs; +} + } // namespace type namespace adaptor { diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index 4619fe0f..7143741e 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -41,6 +41,7 @@ #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" diff --git a/src/Makefile.am b/src/Makefile.am index b15c31a0..8eaad74e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -175,6 +175,7 @@ nobase_include_HEADERS += \ ../include/msgpack/adaptor/adaptor_base.hpp \ ../include/msgpack/adaptor/bool.hpp \ ../include/msgpack/adaptor/boost/fusion.hpp \ + ../include/msgpack/adaptor/boost/msgpack_variant.hpp \ ../include/msgpack/adaptor/boost/optional.hpp \ ../include/msgpack/adaptor/boost/string_ref.hpp \ ../include/msgpack/adaptor/char_ptr.hpp \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f0888588..a0b8e28b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,6 +37,7 @@ LIST (APPEND check_PROGRAMS IF (MSGPACK_BOOST) LIST (APPEND check_PROGRAMS boost_fusion.cpp + boost_variant.cpp boost_optional.cpp boost_string_ref.cpp ) diff --git a/test/Makefile.am b/test/Makefile.am index 165a5e28..37f9de63 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -30,6 +30,7 @@ check_PROGRAMS = \ check_PROGRAMS += \ boost_fusion \ + boost_variant \ boost_optional \ boost_string_ref @@ -77,6 +78,7 @@ shared_ptr_cpp11_SOURCES = shared_ptr_cpp11.cpp unique_ptr_cpp11_SOURCES = unique_ptr_cpp11.cpp boost_fusion_SOURCES = boost_fusion.cpp +boost_variant_SOURCES = boost_variant.cpp boost_optional_SOURCES = boost_optional.cpp boost_string_ref_SOURCES = boost_string_ref.cpp diff --git a/test/boost_variant.cpp b/test/boost_variant.cpp new file mode 100644 index 00000000..109ae22c --- /dev/null +++ b/test/boost_variant.cpp @@ -0,0 +1,770 @@ +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(MSGPACK_USE_BOOST) + +// nil + +TEST(MSGPACK_BOOST, pack_convert_variant_nil) +{ + std::stringstream ss; + msgpack::type::variant val1 = msgpack::type::nil(); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_variant_nil) +{ + msgpack::type::variant val1 = msgpack::type::nil(); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_nil) +{ + msgpack::zone z; + msgpack::type::variant val1 = msgpack::type::nil(); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +// nil (default constructor) + +TEST(MSGPACK_BOOST, pack_convert_variant_nil_default) +{ + std::stringstream ss; + msgpack::type::variant val1; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_variant_nil_default) +{ + msgpack::type::variant val1; + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_nil_default) +{ + msgpack::zone z; + msgpack::type::variant val1; + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +// bool + +TEST(MSGPACK_BOOST, pack_convert_variant_bool) +{ + std::stringstream ss; + msgpack::type::variant val1 = true; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_bool) +{ + msgpack::type::variant val1 = true; + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_bool) +{ + msgpack::zone z; + msgpack::type::variant val1 = true; + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// positive integer + +TEST(MSGPACK_BOOST, pack_convert_variant_positive_integer) +{ + std::stringstream ss; + msgpack::type::variant val1 = uint64_t(123); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_positive_integer) +{ + msgpack::type::variant val1 = uint64_t(123); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_positive_integer) +{ + msgpack::zone z; + msgpack::type::variant val1 = uint64_t(123); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// negative integer + +TEST(MSGPACK_BOOST, pack_convert_variant_negative_integer) +{ + std::stringstream ss; + msgpack::type::variant val1 = int64_t(-123); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_negative_integer) +{ + msgpack::type::variant val1 = int64_t(-123); + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_negative_integer) +{ + msgpack::zone z; + msgpack::type::variant val1 = int64_t(-123); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// float + +TEST(MSGPACK_BOOST, pack_convert_variant_float) +{ + std::stringstream ss; + msgpack::type::variant val1 = 12.34; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_float) +{ + msgpack::type::variant val1 = 12.34; + msgpack::object obj(val1); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_float) +{ + msgpack::zone z; + msgpack::type::variant val1 = 12.34; + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// str + +TEST(MSGPACK_BOOST, pack_convert_variant_str) +{ + std::stringstream ss; + msgpack::type::variant val1 = std::string("ABC"); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_str) +{ + msgpack::zone z; + msgpack::type::variant val1 = std::string("ABC"); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// bin + +TEST(MSGPACK_BOOST, pack_convert_variant_bin) +{ + std::stringstream ss; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant val1 = v; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_bin) +{ + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant val1 = v; + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +// ext + +TEST(MSGPACK_BOOST, pack_convert_variant_ext) +{ + std::stringstream ss; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant val1(msgpack::type::ext(42, v.data(), v.size())); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ext) +{ + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant val1(msgpack::type::ext(42, v.data(), v.size())); + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// array + +TEST(MSGPACK_BOOST, pack_convert_variant_array) +{ + std::stringstream ss; + std::vector v; + v.push_back(msgpack::type::variant(uint64_t(1))); + v.push_back(msgpack::type::variant(int64_t(-1))); + v.push_back(msgpack::type::variant(23.4)); + v.push_back(msgpack::type::variant(std::string("ABC"))); + msgpack::type::variant val1 = v; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_array) +{ + msgpack::zone z; + std::vector v; + v.push_back(msgpack::type::variant(uint64_t(1))); + v.push_back(msgpack::type::variant(int64_t(-1))); + v.push_back(msgpack::type::variant(23.4)); + v.push_back(msgpack::type::variant(std::string("ABC"))); + msgpack::type::variant val1 = v; + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +// multimap + +TEST(MSGPACK_BOOST, pack_convert_variant_map) +{ + std::stringstream ss; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant(uint64_t(1)), msgpack::type::variant(int64_t(-1)))); + v.insert(multimap_t::value_type(msgpack::type::variant(23.4), msgpack::type::variant(std::string("ABC")))); + msgpack::type::variant val1 = v; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_map) +{ + msgpack::zone z; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant(uint64_t(1)), msgpack::type::variant(int64_t(-1)))); + v.insert(multimap_t::value_type(msgpack::type::variant(23.4), msgpack::type::variant(std::string("ABC")))); + msgpack::type::variant val1 = v; + msgpack::object obj(val1, z); + msgpack::type::variant val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// variant_ref + +// nil + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_nil) +{ + std::stringstream ss; + msgpack::type::variant_ref val1 = msgpack::type::nil(); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_variant_ref_nil) +{ + msgpack::type::variant_ref val1 = msgpack::type::nil(); + msgpack::object obj(val1); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_nil) +{ + msgpack::zone z; + msgpack::type::variant_ref val1 = msgpack::type::nil(); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +// nil (default constructor) + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_nil_default) +{ + std::stringstream ss; + msgpack::type::variant_ref val1; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_variant_ref_nil_default) +{ + msgpack::type::variant_ref val1; + msgpack::object obj(val1); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_nil_default) +{ + msgpack::zone z; + msgpack::type::variant_ref val1; + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); +} + +// bool + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_bool) +{ + std::stringstream ss; + msgpack::type::variant_ref val1 = true; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_ref_bool) +{ + msgpack::type::variant_ref val1 = true; + msgpack::object obj(val1); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_bool) +{ + msgpack::zone z; + msgpack::type::variant_ref val1 = true; + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// positive integer + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_positive_integer) +{ + std::stringstream ss; + msgpack::type::variant_ref val1 = uint64_t(123); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_ref_positive_integer) +{ + msgpack::type::variant_ref val1 = uint64_t(123); + msgpack::object obj(val1); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_positive_integer) +{ + msgpack::zone z; + msgpack::type::variant_ref val1 = uint64_t(123); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// negative integer + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_negative_integer) +{ + std::stringstream ss; + msgpack::type::variant_ref val1 = int64_t(-123); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_ref_negative_integer) +{ + msgpack::type::variant_ref val1 = int64_t(-123); + msgpack::object obj(val1); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_negative_integer) +{ + msgpack::zone z; + msgpack::type::variant_ref val1 = int64_t(-123); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// float + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_float) +{ + std::stringstream ss; + msgpack::type::variant_ref val1 = 12.34; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_variant_ref_float) +{ + msgpack::type::variant_ref val1 = 12.34; + msgpack::object obj(val1); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_float) +{ + msgpack::zone z; + msgpack::type::variant_ref val1 = 12.34; + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// str + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_str) +{ + std::stringstream ss; + std::string s("ABC"); + msgpack::type::variant_ref val1 = boost::string_ref(s); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_str) +{ + msgpack::zone z; + std::string s("ABC"); + msgpack::type::variant_ref val1 = boost::string_ref(s); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// bin + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_bin) +{ + std::stringstream ss; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant_ref val1 = msgpack::type::raw_ref(v.data(), v.size()); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_bin) +{ + msgpack::zone z; + std::vector v; + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant_ref val1 = msgpack::type::raw_ref(v.data(), v.size()); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// ext + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_ext) +{ + std::stringstream ss; + std::vector v; + v.push_back(static_cast(42)); + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant_ref val1(msgpack::type::ext_ref(v.data(), v.size())); + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + + + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_ext) +{ + msgpack::zone z; + std::vector v; + v.push_back(static_cast(42)); + v.push_back('a'); + v.push_back('b'); + v.push_back('c'); + msgpack::type::variant_ref val1(msgpack::type::ext_ref(v.data(), v.size())); + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +// array + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_array) +{ + std::stringstream ss; + std::vector v; + v.push_back(msgpack::type::variant_ref(uint64_t(1))); + v.push_back(msgpack::type::variant_ref(int64_t(-1))); + v.push_back(msgpack::type::variant_ref(23.4)); + std::string s("ABC"); + v.push_back(msgpack::type::variant_ref(boost::string_ref(s))); + msgpack::type::variant_ref val1 = v; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_array) +{ + msgpack::zone z; + std::vector v; + v.push_back(msgpack::type::variant_ref(uint64_t(1))); + v.push_back(msgpack::type::variant_ref(int64_t(-1))); + v.push_back(msgpack::type::variant_ref(23.4)); + std::string s("ABC"); + v.push_back(msgpack::type::variant_ref(boost::string_ref(s))); + msgpack::type::variant_ref val1 = v; + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get >(val2)); + EXPECT_TRUE(val1 == val2); +} + +// multimap + +TEST(MSGPACK_BOOST, pack_convert_variant_ref_map) +{ + std::stringstream ss; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant_ref(uint64_t(1)), msgpack::type::variant_ref(int64_t(-1)))); + std::string s("ABC"); + v.insert(multimap_t::value_type(msgpack::type::variant_ref(23.4), msgpack::type::variant_ref(boost::string_ref(s)))); + msgpack::type::variant_ref val1 = v; + + msgpack::pack(ss, val1); + + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + msgpack::type::variant_ref val2 = ret.get().as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +TEST(MSGPACK_BOOST, object_with_zone_variant_ref_map) +{ + msgpack::zone z; + typedef std::multimap multimap_t; + multimap_t v; + v.insert(multimap_t::value_type(msgpack::type::variant_ref(uint64_t(1)), msgpack::type::variant_ref(int64_t(-1)))); + std::string s("ABC"); + v.insert(multimap_t::value_type(msgpack::type::variant_ref(23.4), msgpack::type::variant_ref(boost::string_ref(s)))); + msgpack::type::variant_ref val1 = v; + msgpack::object obj(val1, z); + msgpack::type::variant_ref val2 = obj.as(); + EXPECT_NO_THROW(boost::get(val2)); + EXPECT_TRUE(val1 == val2); +} + +#endif // defined(MSGPACK_USE_BOOST)