From 57ba93a2b230974c6d6334c27bc208e7c85c03f4 Mon Sep 17 00:00:00 2001 From: Takatoshi Kondo Date: Wed, 1 Jul 2015 14:08:54 +0900 Subject: [PATCH 1/2] Added Boost.Fusion support. Fusion sequences can be serialized. --- CMakeLists.txt | 1 + include/msgpack/adaptor/adaptor_base.hpp | 8 +- include/msgpack/adaptor/boost/fusion.hpp | 113 +++++++++++++++++++++++ include/msgpack/object.hpp | 12 +-- include/msgpack/type.hpp | 1 + src/Makefile.am | 1 + test/CMakeLists.txt | 1 + test/Makefile.am | 3 + test/boost_fusion.cpp | 47 ++++++++++ 9 files changed, 177 insertions(+), 10 deletions(-) create mode 100644 include/msgpack/adaptor/boost/fusion.hpp create mode 100644 test/boost_fusion.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cdbf22a..dfddb73b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,7 @@ IF (MSGPACK_ENABLE_CXX) include/msgpack.hpp include/msgpack/adaptor/adaptor_base.hpp include/msgpack/adaptor/bool.hpp + include/msgpack/adaptor/boost/fusion.hpp include/msgpack/adaptor/boost/optional.hpp include/msgpack/adaptor/boost/string_ref.hpp include/msgpack/adaptor/char_ptr.hpp diff --git a/include/msgpack/adaptor/adaptor_base.hpp b/include/msgpack/adaptor/adaptor_base.hpp index e5f1560c..e318eedd 100644 --- a/include/msgpack/adaptor/adaptor_base.hpp +++ b/include/msgpack/adaptor/adaptor_base.hpp @@ -33,23 +33,23 @@ namespace adaptor { // Adaptor functors -template +template struct convert { msgpack::object const& operator()(msgpack::object const& o, T& v) const; }; -template +template struct pack { template msgpack::packer& operator()(msgpack::packer& o, T const& v) const; }; -template +template struct object { void operator()(msgpack::object& o, T const& v) const; }; -template +template struct object_with_zone { void operator()(msgpack::object::with_zone& o, T const& v) const; }; diff --git a/include/msgpack/adaptor/boost/fusion.hpp b/include/msgpack/adaptor/boost/fusion.hpp new file mode 100644 index 00000000..b0f0e7df --- /dev/null +++ b/include/msgpack/adaptor/boost/fusion.hpp @@ -0,0 +1,113 @@ +// +// 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_FUSION_HPP +#define MSGPACK_TYPE_BOOST_FUSION_HPP + +#include "msgpack/versioning.hpp" +#include "msgpack/adaptor/adaptor_base.hpp" +#include "msgpack/adaptor/check_container_size.hpp" + +#include +#include +#include + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +namespace adaptor { + +template +struct convert::value>::type > { + 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 != checked_get_container_size(boost::fusion::size(v))) { + throw msgpack::type_error(); + } + uint32_t index = 0; + boost::fusion::for_each(v, convert_imp(o, index)); + return o; + } +private: + struct convert_imp { + convert_imp(msgpack::object const& obj, uint32_t& index):obj_(obj), index_(index) {} + template + void operator()(U& v) const { + msgpack::adaptor::convert()(obj_.via.array.ptr[index_++], v); + } + private: + msgpack::object const& obj_; + uint32_t& index_; + }; +}; + +template +struct pack::value>::type > { + template + msgpack::packer& operator()(msgpack::packer& o, const T& v) const { + uint32_t size = checked_get_container_size(boost::fusion::size(v)); + o.pack_array(size); + boost::fusion::for_each(v, pack_imp(o)); + return o; + } +private: + template + struct pack_imp { + pack_imp(msgpack::packer& stream):stream_(stream) {} + template + void operator()(U const& v) const { + stream_.pack(v); + } + private: + msgpack::packer& stream_; + }; +}; + +template +struct object_with_zone::value>::type > { + void operator()(msgpack::object::with_zone& o, const T& v) const { + uint32_t size = checked_get_container_size(boost::fusion::size(v)); + o.type = msgpack::type::ARRAY; + o.via.array.ptr = static_cast(o.zone.allocate_align(sizeof(msgpack::object)*size)); + o.via.array.size = size; + uint32_t count = 0; + boost::fusion::for_each(v, with_zone_imp(o, count)); + } +private: + struct with_zone_imp { + with_zone_imp(msgpack::object::with_zone const& obj, uint32_t& count):obj_(obj), count_(count) {} + template + void operator()(U const& v) const { + obj_.via.array.ptr[count_++] = msgpack::object(v, obj_.zone); + } + msgpack::object::with_zone const& obj_; + uint32_t& count_; + }; +}; + +} // namespace adaptor + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_TYPE_BOOST_FUSION_HPP diff --git a/include/msgpack/object.hpp b/include/msgpack/object.hpp index fe40f844..1960ee2c 100644 --- a/include/msgpack/object.hpp +++ b/include/msgpack/object.hpp @@ -169,26 +169,26 @@ struct packer_serializer { } // namespace detail // Adaptor functors' member functions definitions. -template +template inline msgpack::object const& -msgpack::adaptor::convert::operator()(msgpack::object const& o, T& v) const { +msgpack::adaptor::convert::operator()(msgpack::object const& o, T& v) const { v.msgpack_unpack(o.convert()); return o; } -template +template template inline msgpack::packer& -msgpack::adaptor::pack::operator()(msgpack::packer& o, T const& v) const { +msgpack::adaptor::pack::operator()(msgpack::packer& o, T const& v) const { return detail::packer_serializer::pack(o, v); } -template +template inline void -msgpack::adaptor::object_with_zone::operator()(msgpack::object::with_zone& o, T const& v) const { +msgpack::adaptor::object_with_zone::operator()(msgpack::object::with_zone& o, T const& v) const { v.msgpack_object(static_cast(&o), o.zone); } diff --git a/include/msgpack/type.hpp b/include/msgpack/type.hpp index 2300a0f4..911a3dcc 100644 --- a/include/msgpack/type.hpp +++ b/include/msgpack/type.hpp @@ -36,6 +36,7 @@ #if defined(MSGPACK_USE_BOOST) +#include "adaptor/boost/fusion.hpp" #include "adaptor/boost/optional.hpp" #include "adaptor/boost/string_ref.hpp" diff --git a/src/Makefile.am b/src/Makefile.am index b5dafe60..fc3716f0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,7 @@ nobase_include_HEADERS += \ ../include/msgpack.hpp \ ../include/msgpack/adaptor/adaptor_base.hpp \ ../include/msgpack/adaptor/bool.hpp \ + ../include/msgpack/adaptor/boost/fusion.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 24e7befe..f1b8b974 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,6 +34,7 @@ LIST (APPEND check_PROGRAMS IF (MSGPACK_BOOST) LIST (APPEND check_PROGRAMS + boost_fusion.cpp boost_optional.cpp boost_string_ref.cpp ) diff --git a/test/Makefile.am b/test/Makefile.am index 5a8a2872..fee60cd6 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -28,6 +28,7 @@ check_PROGRAMS = \ limit \ json \ iterator_cpp11 \ + boost_fusion \ boost_optional \ boost_string_ref @@ -84,6 +85,8 @@ json_SOURCES = json.cpp iterator_cpp11_SOURCES = iterator_cpp11.cpp +boost_fusion_SOURCES = boost_fusion.cpp + boost_optional_SOURCES = boost_optional.cpp boost_string_ref_SOURCES = boost_string_ref.cpp diff --git a/test/boost_fusion.cpp b/test/boost_fusion.cpp new file mode 100644 index 00000000..6c07cc46 --- /dev/null +++ b/test/boost_fusion.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(MSGPACK_USE_BOOST) + +#include + +BOOST_FUSION_DEFINE_STRUCT( + BOOST_PP_EMPTY(), + mystruct, + (int, f1) + (double, f2) + ) + +TEST(MSGPACK_BOOST, fusion_pack_unpack_convert) +{ + std::stringstream ss; + mystruct val1; + val1.f1 = 42; + val1.f2 = 123.45; + msgpack::pack(ss, val1); + msgpack::unpacked ret; + msgpack::unpack(ret, ss.str().data(), ss.str().size()); + mystruct val2 = ret.get().as(); + EXPECT_TRUE(val1.f1 == val2.f1); + EXPECT_TRUE(val1.f2 == val2.f2); +} + +TEST(MSGPACK_BOOST, object_with_zone_convert) +{ + mystruct val1; + val1.f1 = 42; + val1.f2 = 123.45; + msgpack::zone z; + msgpack::object obj(val1, z); + mystruct val2 = obj.as(); + EXPECT_TRUE(val1.f1 == val2.f1); + EXPECT_TRUE(val1.f2 == val2.f2); +} + +#endif // defined(MSGPACK_USE_BOOST) From 6131e3d747b183b2cac9a3e95c3c6af36b2f4ce8 Mon Sep 17 00:00:00 2001 From: Takatoshi Kondo Date: Sat, 4 Jul 2015 22:49:47 +0900 Subject: [PATCH 2/2] Fixed double comparison in tests. --- test/boost_fusion.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/boost_fusion.cpp b/test/boost_fusion.cpp index 6c07cc46..a0fb24f6 100644 --- a/test/boost_fusion.cpp +++ b/test/boost_fusion.cpp @@ -1,6 +1,8 @@ #include #include #include +#include + #include #ifdef HAVE_CONFIG_H @@ -11,6 +13,8 @@ #include +const double kEPS = 1e-10; + BOOST_FUSION_DEFINE_STRUCT( BOOST_PP_EMPTY(), mystruct, @@ -29,7 +33,7 @@ TEST(MSGPACK_BOOST, fusion_pack_unpack_convert) msgpack::unpack(ret, ss.str().data(), ss.str().size()); mystruct val2 = ret.get().as(); EXPECT_TRUE(val1.f1 == val2.f1); - EXPECT_TRUE(val1.f2 == val2.f2); + EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS); } TEST(MSGPACK_BOOST, object_with_zone_convert) @@ -41,7 +45,7 @@ TEST(MSGPACK_BOOST, object_with_zone_convert) msgpack::object obj(val1, z); mystruct val2 = obj.as(); EXPECT_TRUE(val1.f1 == val2.f1); - EXPECT_TRUE(val1.f2 == val2.f2); + EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS); } #endif // defined(MSGPACK_USE_BOOST)