Skip to content

Commit a37e723

Browse files
committed
Merge pull request #305 from redboltz/add_boost_fusion
Added Boost.Fusion support.
2 parents b559187 + 6131e3d commit a37e723

File tree

9 files changed

+181
-10
lines changed

9 files changed

+181
-10
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ IF (MSGPACK_ENABLE_CXX)
105105
include/msgpack.hpp
106106
include/msgpack/adaptor/adaptor_base.hpp
107107
include/msgpack/adaptor/bool.hpp
108+
include/msgpack/adaptor/boost/fusion.hpp
108109
include/msgpack/adaptor/boost/optional.hpp
109110
include/msgpack/adaptor/boost/string_ref.hpp
110111
include/msgpack/adaptor/char_ptr.hpp

include/msgpack/adaptor/adaptor_base.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ namespace adaptor {
3333

3434
// Adaptor functors
3535

36-
template <typename T>
36+
template <typename T, typename Enabler = void>
3737
struct convert {
3838
msgpack::object const& operator()(msgpack::object const& o, T& v) const;
3939
};
4040

41-
template <typename T>
41+
template <typename T, typename Enabler = void>
4242
struct pack {
4343
template <typename Stream>
4444
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, T const& v) const;
4545
};
4646

47-
template <typename T>
47+
template <typename T, typename Enabler = void>
4848
struct object {
4949
void operator()(msgpack::object& o, T const& v) const;
5050
};
5151

52-
template <typename T>
52+
template <typename T, typename Enabler = void>
5353
struct object_with_zone {
5454
void operator()(msgpack::object::with_zone& o, T const& v) const;
5555
};
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//
2+
// MessagePack for C++ static resolution routine
3+
//
4+
// Copyright (C) 2015 KONDO Takatoshi
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
#ifndef MSGPACK_TYPE_BOOST_FUSION_HPP
19+
#define MSGPACK_TYPE_BOOST_FUSION_HPP
20+
21+
#include "msgpack/versioning.hpp"
22+
#include "msgpack/adaptor/adaptor_base.hpp"
23+
#include "msgpack/adaptor/check_container_size.hpp"
24+
25+
#include <boost/fusion/support/is_sequence.hpp>
26+
#include <boost/fusion/sequence/intrinsic/size.hpp>
27+
#include <boost/fusion/algorithm/iteration/for_each.hpp>
28+
29+
namespace msgpack {
30+
31+
/// @cond
32+
MSGPACK_API_VERSION_NAMESPACE(v1) {
33+
/// @endcond
34+
35+
namespace adaptor {
36+
37+
template <typename T>
38+
struct convert<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > {
39+
msgpack::object const& operator()(msgpack::object const& o, T& v) const {
40+
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
41+
if(o.via.array.size != checked_get_container_size(boost::fusion::size(v))) {
42+
throw msgpack::type_error();
43+
}
44+
uint32_t index = 0;
45+
boost::fusion::for_each(v, convert_imp(o, index));
46+
return o;
47+
}
48+
private:
49+
struct convert_imp {
50+
convert_imp(msgpack::object const& obj, uint32_t& index):obj_(obj), index_(index) {}
51+
template <typename U>
52+
void operator()(U& v) const {
53+
msgpack::adaptor::convert<U>()(obj_.via.array.ptr[index_++], v);
54+
}
55+
private:
56+
msgpack::object const& obj_;
57+
uint32_t& index_;
58+
};
59+
};
60+
61+
template <typename T>
62+
struct pack<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > {
63+
template <typename Stream>
64+
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const T& v) const {
65+
uint32_t size = checked_get_container_size(boost::fusion::size(v));
66+
o.pack_array(size);
67+
boost::fusion::for_each(v, pack_imp<Stream>(o));
68+
return o;
69+
}
70+
private:
71+
template <typename Stream>
72+
struct pack_imp {
73+
pack_imp(msgpack::packer<Stream>& stream):stream_(stream) {}
74+
template <typename U>
75+
void operator()(U const& v) const {
76+
stream_.pack(v);
77+
}
78+
private:
79+
msgpack::packer<Stream>& stream_;
80+
};
81+
};
82+
83+
template <typename T>
84+
struct object_with_zone<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > {
85+
void operator()(msgpack::object::with_zone& o, const T& v) const {
86+
uint32_t size = checked_get_container_size(boost::fusion::size(v));
87+
o.type = msgpack::type::ARRAY;
88+
o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size));
89+
o.via.array.size = size;
90+
uint32_t count = 0;
91+
boost::fusion::for_each(v, with_zone_imp(o, count));
92+
}
93+
private:
94+
struct with_zone_imp {
95+
with_zone_imp(msgpack::object::with_zone const& obj, uint32_t& count):obj_(obj), count_(count) {}
96+
template <typename U>
97+
void operator()(U const& v) const {
98+
obj_.via.array.ptr[count_++] = msgpack::object(v, obj_.zone);
99+
}
100+
msgpack::object::with_zone const& obj_;
101+
uint32_t& count_;
102+
};
103+
};
104+
105+
} // namespace adaptor
106+
107+
/// @cond
108+
} // MSGPACK_API_VERSION_NAMESPACE(v1)
109+
/// @endcond
110+
111+
} // namespace msgpack
112+
113+
#endif // MSGPACK_TYPE_BOOST_FUSION_HPP

include/msgpack/object.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,26 +170,26 @@ struct packer_serializer {
170170
} // namespace detail
171171

172172
// Adaptor functors' member functions definitions.
173-
template <typename T>
173+
template <typename T, typename Enabler>
174174
inline
175175
msgpack::object const&
176-
msgpack::adaptor::convert<T>::operator()(msgpack::object const& o, T& v) const {
176+
msgpack::adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
177177
v.msgpack_unpack(o.convert());
178178
return o;
179179
}
180180

181-
template <typename T>
181+
template <typename T, typename Enabler>
182182
template <typename Stream>
183183
inline
184184
msgpack::packer<Stream>&
185-
msgpack::adaptor::pack<T>::operator()(msgpack::packer<Stream>& o, T const& v) const {
185+
msgpack::adaptor::pack<T, Enabler>::operator()(msgpack::packer<Stream>& o, T const& v) const {
186186
return detail::packer_serializer<Stream, T>::pack(o, v);
187187
}
188188

189-
template <typename T>
189+
template <typename T, typename Enabler>
190190
inline
191191
void
192-
msgpack::adaptor::object_with_zone<T>::operator()(msgpack::object::with_zone& o, T const& v) const {
192+
msgpack::adaptor::object_with_zone<T, Enabler>::operator()(msgpack::object::with_zone& o, T const& v) const {
193193
v.msgpack_object(static_cast<msgpack::object*>(&o), o.zone);
194194
}
195195

include/msgpack/type.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#if defined(MSGPACK_USE_BOOST)
3939

40+
#include "adaptor/boost/fusion.hpp"
4041
#include "adaptor/boost/optional.hpp"
4142
#include "adaptor/boost/string_ref.hpp"
4243

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ nobase_include_HEADERS += \
5656
../include/msgpack.hpp \
5757
../include/msgpack/adaptor/adaptor_base.hpp \
5858
../include/msgpack/adaptor/bool.hpp \
59+
../include/msgpack/adaptor/boost/fusion.hpp \
5960
../include/msgpack/adaptor/boost/optional.hpp \
6061
../include/msgpack/adaptor/boost/string_ref.hpp \
6162
../include/msgpack/adaptor/char_ptr.hpp \

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ LIST (APPEND check_PROGRAMS
3535

3636
IF (MSGPACK_BOOST)
3737
LIST (APPEND check_PROGRAMS
38+
boost_fusion.cpp
3839
boost_optional.cpp
3940
boost_string_ref.cpp
4041
)

test/Makefile.am

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ check_PROGRAMS = \
2929
json \
3030
raw \
3131
iterator_cpp11 \
32+
boost_fusion \
3233
boost_optional \
3334
boost_string_ref
3435

@@ -87,6 +88,8 @@ raw_SOURCES = raw.cpp
8788

8889
iterator_cpp11_SOURCES = iterator_cpp11.cpp
8990

91+
boost_fusion_SOURCES = boost_fusion.cpp
92+
9093
boost_optional_SOURCES = boost_optional.cpp
9194

9295
boost_string_ref_SOURCES = boost_string_ref.cpp

test/boost_fusion.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <msgpack.hpp>
2+
#include <sstream>
3+
#include <iterator>
4+
#include <cmath>
5+
6+
#include <gtest/gtest.h>
7+
8+
#ifdef HAVE_CONFIG_H
9+
#include "config.h"
10+
#endif
11+
12+
#if defined(MSGPACK_USE_BOOST)
13+
14+
#include <boost/fusion/adapted/struct/define_struct.hpp>
15+
16+
const double kEPS = 1e-10;
17+
18+
BOOST_FUSION_DEFINE_STRUCT(
19+
BOOST_PP_EMPTY(),
20+
mystruct,
21+
(int, f1)
22+
(double, f2)
23+
)
24+
25+
TEST(MSGPACK_BOOST, fusion_pack_unpack_convert)
26+
{
27+
std::stringstream ss;
28+
mystruct val1;
29+
val1.f1 = 42;
30+
val1.f2 = 123.45;
31+
msgpack::pack(ss, val1);
32+
msgpack::unpacked ret;
33+
msgpack::unpack(ret, ss.str().data(), ss.str().size());
34+
mystruct val2 = ret.get().as<mystruct>();
35+
EXPECT_TRUE(val1.f1 == val2.f1);
36+
EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS);
37+
}
38+
39+
TEST(MSGPACK_BOOST, object_with_zone_convert)
40+
{
41+
mystruct val1;
42+
val1.f1 = 42;
43+
val1.f2 = 123.45;
44+
msgpack::zone z;
45+
msgpack::object obj(val1, z);
46+
mystruct val2 = obj.as<mystruct>();
47+
EXPECT_TRUE(val1.f1 == val2.f1);
48+
EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS);
49+
}
50+
51+
#endif // defined(MSGPACK_USE_BOOST)

0 commit comments

Comments
 (0)