mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-05-25 22:44:05 +02:00
Merge pull request #305 from redboltz/add_boost_fusion
Added Boost.Fusion support.
This commit is contained in:
commit
a37e7232c7
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
113
include/msgpack/adaptor/boost/fusion.hpp
Normal file
113
include/msgpack/adaptor/boost/fusion.hpp
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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
51
test/boost_fusion.cpp
Normal 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)
|
Loading…
x
Reference in New Issue
Block a user