Hideaki Tai / msgpack-embedded

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cpp11_define_map.hpp Source File

cpp11_define_map.hpp

00001 //
00002 // MessagePack for C++ static resolution routine
00003 //
00004 // Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi
00005 //
00006 //    Distributed under the Boost Software License, Version 1.0.
00007 //    (See accompanying file LICENSE_1_0.txt or copy at
00008 //    http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 #ifndef MSGPACK_CPP11_DEFINE_MAP_HPP
00011 #define MSGPACK_CPP11_DEFINE_MAP_HPP
00012 
00013 // BOOST_PP_VARIADICS is defined in boost/preprocessor/config/config.hpp
00014 // http://www.boost.org/libs/preprocessor/doc/ref/variadics.html
00015 // However, supporting compiler detection is not complete. msgpack-c requires
00016 // variadic macro arguments support. So BOOST_PP_VARIADICS is defined here explicitly.
00017 #if !defined(MSGPACK_PP_VARIADICS)
00018 #define MSGPACK_PP_VARIADICS
00019 #endif
00020 
00021 #include <msgpack/preprocessor.hpp>
00022 
00023 #include "msgpack/versioning.hpp"
00024 #include "msgpack/adaptor/adaptor_base.hpp"
00025 
00026 // for MSGPACK_ADD_ENUM
00027 #include "msgpack/adaptor/int.hpp"
00028 
00029 #include <type_traits>
00030 #include <tuple>
00031 
00032 #define MSGPACK_DEFINE_MAP_EACH_PROC(r, data, elem) \
00033     MSGPACK_PP_IF( \
00034         MSGPACK_PP_IS_BEGIN_PARENS(elem), \
00035         elem, \
00036         (MSGPACK_PP_STRINGIZE(elem))(elem) \
00037     )
00038 
00039 #define MSGPACK_DEFINE_MAP_IMPL(...) \
00040     MSGPACK_PP_SEQ_TO_TUPLE( \
00041         MSGPACK_PP_SEQ_FOR_EACH( \
00042             MSGPACK_DEFINE_MAP_EACH_PROC, \
00043             0, \
00044             MSGPACK_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \
00045         ) \
00046     )
00047 
00048 #define MSGPACK_DEFINE_MAP(...) \
00049     template <typename Packer> \
00050     void msgpack_pack(Packer& pk) const \
00051     { \
00052         msgpack::type::make_define_map \
00053             MSGPACK_DEFINE_MAP_IMPL(__VA_ARGS__) \
00054             .msgpack_pack(pk); \
00055     } \
00056     void msgpack_unpack(msgpack::object const& o) \
00057     { \
00058         msgpack::type::make_define_map \
00059             MSGPACK_DEFINE_MAP_IMPL(__VA_ARGS__) \
00060             .msgpack_unpack(o); \
00061     }\
00062     template <typename MSGPACK_OBJECT> \
00063     void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone& z) const \
00064     { \
00065         msgpack::type::make_define_map \
00066             MSGPACK_DEFINE_MAP_IMPL(__VA_ARGS__) \
00067             .msgpack_object(o, z); \
00068     }
00069 
00070 #define MSGPACK_BASE_MAP(base) \
00071     (MSGPACK_PP_STRINGIZE(base))(*const_cast<base *>(static_cast<base const*>(this)))
00072 
00073 namespace msgpack {
00074 /// @cond
00075 MSGPACK_API_VERSION_NAMESPACE(v1) {
00076 /// @endcond
00077 namespace type {
00078 
00079 template <typename Tuple, std::size_t N>
00080 struct define_map_imp {
00081     template <typename Packer>
00082     static void pack(Packer& pk, Tuple const& t) {
00083         define_map_imp<Tuple, N-1>::pack(pk, t);
00084         pk.pack(std::get<N-1>(t));
00085     }
00086     static void unpack(
00087         msgpack::object const& o, Tuple const& t,
00088         std::map<std::string, msgpack::object const*> const& kvmap) {
00089         define_map_imp<Tuple, N-2>::unpack(o, t, kvmap);
00090         auto it = kvmap.find(std::get<N-2>(t));
00091         if (it != kvmap.end()) {
00092             it->second->convert(std::get<N-1>(t));
00093         }
00094     }
00095     static void object(msgpack::object* o, msgpack::zone& z, Tuple const& t) {
00096         define_map_imp<Tuple, N-2>::object(o, z, t);
00097         o->via.map.ptr[(N-1)/2].key = msgpack::object(std::get<N-2>(t), z);
00098         o->via.map.ptr[(N-1)/2].val = msgpack::object(std::get<N-1>(t), z);
00099     }
00100 };
00101 
00102 template <typename Tuple>
00103 struct define_map_imp<Tuple, 0> {
00104     template <typename Packer>
00105     static void pack(Packer&, Tuple const&) {}
00106     static void unpack(
00107         msgpack::object const&, Tuple const&,
00108         std::map<std::string, msgpack::object const*> const&) {}
00109     static void object(msgpack::object*, msgpack::zone&, Tuple const&) {}
00110 };
00111 
00112 template <typename... Args>
00113 struct define_map {
00114     define_map(Args&... args) :
00115         a(args...) {}
00116     template <typename Packer>
00117     void msgpack_pack(Packer& pk) const
00118     {
00119         static_assert(sizeof...(Args) % 2 == 0, "");
00120         pk.pack_map(sizeof...(Args) / 2);
00121 
00122         define_map_imp<std::tuple<Args&...>, sizeof...(Args)>::pack(pk, a);
00123     }
00124     void msgpack_unpack(msgpack::object const& o) const
00125     {
00126         if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
00127         std::map<std::string, msgpack::object const*> kvmap;
00128         for (uint32_t i = 0; i < o.via.map.size; ++i) {
00129             kvmap.emplace(
00130                 std::string(
00131                     o.via.map.ptr[i].key.via.str.ptr,
00132                     o.via.map.ptr[i].key.via.str.size),
00133                 &o.via.map.ptr[i].val);
00134         }
00135         define_map_imp<std::tuple<Args&...>, sizeof...(Args)>::unpack(o, a, kvmap);
00136     }
00137     void msgpack_object(msgpack::object* o, msgpack::zone& z) const
00138     {
00139         static_assert(sizeof...(Args) % 2 == 0, "");
00140         o->type = msgpack::type::MAP;
00141         o->via.map.ptr = static_cast<msgpack::object_kv*>(z.allocate_align(sizeof(msgpack::object_kv)*sizeof...(Args)/2));
00142         o->via.map.size = sizeof...(Args) / 2;
00143 
00144         define_map_imp<std::tuple<Args&...>, sizeof...(Args)>::object(o, z, a);
00145     }
00146 
00147     std::tuple<Args&...> a;
00148 };
00149 
00150 
00151 template <typename... Args>
00152 define_map<Args...> make_define_map(Args&... args)
00153 {
00154     return define_map<Args...>(args...);
00155 }
00156 
00157 }  // namespace type
00158 /// @cond
00159 }  // MSGPACK_API_VERSION_NAMESPACE(v1)
00160 /// @endcond
00161 }  // namespace msgpack
00162 
00163 #endif // MSGPACK_CPP11_DEFINE_MAP_HPP
00164