Merge pull request #305 from redboltz/add_boost_fusion

Added Boost.Fusion support.
This commit is contained in:
Takatoshi Kondo 2015-07-05 10:34:06 +09:00
commit a37e7232c7
9 changed files with 181 additions and 10 deletions

View File

@ -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

View File

@ -33,23 +33,23 @@ namespace adaptor {
// Adaptor functors
template <typename T>
template <typename T, typename Enabler = void>
struct convert {
msgpack::object const& operator()(msgpack::object const& o, T& v) const;
};
template <typename T>
template <typename T, typename Enabler = void>
struct pack {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, T const& v) const;
};
template <typename T>
template <typename T, typename Enabler = void>
struct object {
void operator()(msgpack::object& o, T const& v) const;
};
template <typename T>
template <typename T, typename Enabler = void>
struct object_with_zone {
void operator()(msgpack::object::with_zone& o, T const& v) const;
};

View File

@ -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 <boost/fusion/support/is_sequence.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
namespace msgpack {
/// @cond
MSGPACK_API_VERSION_NAMESPACE(v1) {
/// @endcond
namespace adaptor {
template <typename T>
struct convert<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::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 <typename U>
void operator()(U& v) const {
msgpack::adaptor::convert<U>()(obj_.via.array.ptr[index_++], v);
}
private:
msgpack::object const& obj_;
uint32_t& index_;
};
};
template <typename T>
struct pack<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& 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<Stream>(o));
return o;
}
private:
template <typename Stream>
struct pack_imp {
pack_imp(msgpack::packer<Stream>& stream):stream_(stream) {}
template <typename U>
void operator()(U const& v) const {
stream_.pack(v);
}
private:
msgpack::packer<Stream>& stream_;
};
};
template <typename T>
struct object_with_zone<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::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<msgpack::object*>(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 <typename U>
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

View File

@ -170,26 +170,26 @@ struct packer_serializer {
} // namespace detail
// Adaptor functors' member functions definitions.
template <typename T>
template <typename T, typename Enabler>
inline
msgpack::object const&
msgpack::adaptor::convert<T>::operator()(msgpack::object const& o, T& v) const {
msgpack::adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
v.msgpack_unpack(o.convert());
return o;
}
template <typename T>
template <typename T, typename Enabler>
template <typename Stream>
inline
msgpack::packer<Stream>&
msgpack::adaptor::pack<T>::operator()(msgpack::packer<Stream>& o, T const& v) const {
msgpack::adaptor::pack<T, Enabler>::operator()(msgpack::packer<Stream>& o, T const& v) const {
return detail::packer_serializer<Stream, T>::pack(o, v);
}
template <typename T>
template <typename T, typename Enabler>
inline
void
msgpack::adaptor::object_with_zone<T>::operator()(msgpack::object::with_zone& o, T const& v) const {
msgpack::adaptor::object_with_zone<T, Enabler>::operator()(msgpack::object::with_zone& o, T const& v) const {
v.msgpack_object(static_cast<msgpack::object*>(&o), o.zone);
}

View File

@ -37,6 +37,7 @@
#if defined(MSGPACK_USE_BOOST)
#include "adaptor/boost/fusion.hpp"
#include "adaptor/boost/optional.hpp"
#include "adaptor/boost/string_ref.hpp"

View File

@ -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 \

View File

@ -35,6 +35,7 @@ LIST (APPEND check_PROGRAMS
IF (MSGPACK_BOOST)
LIST (APPEND check_PROGRAMS
boost_fusion.cpp
boost_optional.cpp
boost_string_ref.cpp
)

View File

@ -29,6 +29,7 @@ check_PROGRAMS = \
json \
raw \
iterator_cpp11 \
boost_fusion \
boost_optional \
boost_string_ref
@ -87,6 +88,8 @@ raw_SOURCES = raw.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

51
test/boost_fusion.cpp Normal file
View File

@ -0,0 +1,51 @@
#include <msgpack.hpp>
#include <sstream>
#include <iterator>
#include <cmath>
#include <gtest/gtest.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(MSGPACK_USE_BOOST)
#include <boost/fusion/adapted/struct/define_struct.hpp>
const double kEPS = 1e-10;
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<mystruct>();
EXPECT_TRUE(val1.f1 == val2.f1);
EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS);
}
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<mystruct>();
EXPECT_TRUE(val1.f1 == val2.f1);
EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS);
}
#endif // defined(MSGPACK_USE_BOOST)