Hideaki Tai / msgpack-embedded

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cpp11_define_array.hpp Source File

cpp11_define_array.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_ARRAY_HPP
00011 #define MSGPACK_CPP11_DEFINE_ARRAY_HPP
00012 
00013 #include "msgpack/versioning.hpp"
00014 #include "msgpack/adaptor/adaptor_base.hpp"
00015 
00016 // for MSGPACK_ADD_ENUM
00017 #include "msgpack/adaptor/int.hpp"
00018 
00019 #include <type_traits>
00020 #include <tuple>
00021 
00022 #define MSGPACK_DEFINE_ARRAY(...) \
00023     template <typename Packer> \
00024     void msgpack_pack(Packer& pk) const \
00025     { \
00026         msgpack::type::make_define_array(__VA_ARGS__).msgpack_pack(pk); \
00027     } \
00028     void msgpack_unpack(msgpack::object const& o) \
00029     { \
00030         msgpack::type::make_define_array(__VA_ARGS__).msgpack_unpack(o); \
00031     }\
00032     template <typename MSGPACK_OBJECT> \
00033     void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone& z) const \
00034     { \
00035         msgpack::type::make_define_array(__VA_ARGS__).msgpack_object(o, z); \
00036     }
00037 
00038 #define MSGPACK_BASE_ARRAY(base) (*const_cast<base *>(static_cast<base const*>(this)))
00039 
00040 // MSGPACK_ADD_ENUM must be used in the global namespace.
00041 #define MSGPACK_ADD_ENUM(enum_name) \
00042   namespace msgpack { \
00043   /** @cond */ \
00044   MSGPACK_API_VERSION_NAMESPACE(v1) { \
00045   /** @endcond */ \
00046   namespace adaptor { \
00047     template<> \
00048     struct convert<enum_name> { \
00049       msgpack::object const& operator()(msgpack::object const& o, enum_name& v) const { \
00050         std::underlying_type<enum_name>::type tmp; \
00051         o >> tmp; \
00052         v = static_cast<enum_name>(tmp);   \
00053         return o; \
00054       } \
00055     }; \
00056     template<> \
00057     struct object<enum_name> { \
00058       void operator()(msgpack::object& o, const enum_name& v) const { \
00059         auto tmp = static_cast<std::underlying_type<enum_name>::type>(v); \
00060         o << tmp; \
00061       } \
00062     }; \
00063     template<> \
00064     struct object_with_zone<enum_name> { \
00065       void operator()(msgpack::object::with_zone& o, const enum_name& v) const {  \
00066         auto tmp = static_cast<std::underlying_type<enum_name>::type>(v); \
00067         o << tmp; \
00068       } \
00069     }; \
00070     template <> \
00071     struct pack<enum_name> { \
00072       template <typename Stream> \
00073       msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const enum_name& v) const { \
00074         return o << static_cast<std::underlying_type<enum_name>::type>(v); \
00075       } \
00076     }; \
00077   } \
00078   /** @cond */ \
00079   } \
00080   /** @endcond */ \
00081   }
00082 
00083 namespace msgpack {
00084 /// @cond
00085 MSGPACK_API_VERSION_NAMESPACE(v1) {
00086 /// @endcond
00087 namespace type {
00088 
00089 template <typename Tuple, std::size_t N>
00090 struct define_array_imp {
00091     template <typename Packer>
00092     static void pack(Packer& pk, Tuple const& t) {
00093         define_array_imp<Tuple, N-1>::pack(pk, t);
00094         pk.pack(std::get<N-1>(t));
00095     }
00096     static void unpack(msgpack::object const& o, Tuple& t) {
00097         define_array_imp<Tuple, N-1>::unpack(o, t);
00098         const size_t size = o.via.array.size;
00099         if(size <= N-1) { return; }
00100         o.via.array.ptr[N-1].convert(std::get<N-1>(t));
00101     }
00102     static void object(msgpack::object* o, msgpack::zone& z, Tuple const& t) {
00103         define_array_imp<Tuple, N-1>::object(o, z, t);
00104         o->via.array.ptr[N-1] = msgpack::object(std::get<N-1>(t), z);
00105     }
00106 };
00107 
00108 template <typename Tuple>
00109 struct define_array_imp<Tuple, 1> {
00110     template <typename Packer>
00111     static void pack(Packer& pk, Tuple const& t) {
00112         pk.pack(std::get<0>(t));
00113     }
00114     static void unpack(msgpack::object const& o, Tuple& t) {
00115         const size_t size = o.via.array.size;
00116         if(size <= 0) { return; }
00117         o.via.array.ptr[0].convert(std::get<0>(t));
00118     }
00119     static void object(msgpack::object* o, msgpack::zone& z, Tuple const& t) {
00120         o->via.array.ptr[0] = msgpack::object(std::get<0>(t), z);
00121     }
00122 };
00123 
00124 template <typename... Args>
00125 struct define_array {
00126     typedef define_array<Args...> value_type;
00127     typedef std::tuple<Args...> tuple_type;
00128     define_array(Args&... args) :
00129         a(args...) {}
00130     template <typename Packer>
00131     void msgpack_pack(Packer& pk) const
00132     {
00133         pk.pack_array(sizeof...(Args));
00134 
00135         define_array_imp<std::tuple<Args&...>, sizeof...(Args)>::pack(pk, a);
00136     }
00137     void msgpack_unpack(msgpack::object const& o)
00138     {
00139         if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
00140 
00141         define_array_imp<std::tuple<Args&...>, sizeof...(Args)>::unpack(o, a);
00142     }
00143     void msgpack_object(msgpack::object* o, msgpack::zone& z) const
00144     {
00145         o->type = msgpack::type::ARRAY;
00146         o->via.array.ptr = static_cast<msgpack::object*>(z.allocate_align(sizeof(msgpack::object)*sizeof...(Args)));
00147         o->via.array.size = sizeof...(Args);
00148 
00149         define_array_imp<std::tuple<Args&...>, sizeof...(Args)>::object(o, z, a);
00150     }
00151 
00152     std::tuple<Args&...> a;
00153 };
00154 
00155 template <>
00156 struct define_array<> {
00157     typedef define_array<> value_type;
00158     typedef std::tuple<> tuple_type;
00159     template <typename Packer>
00160     void msgpack_pack(Packer& pk) const
00161     {
00162         pk.pack_array(0);
00163     }
00164     void msgpack_unpack(msgpack::object const& o)
00165     {
00166         if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
00167     }
00168     void msgpack_object(msgpack::object* o, msgpack::zone&) const
00169     {
00170         o->type = msgpack::type::ARRAY;
00171         o->via.array.ptr = NULL;
00172         o->via.array.size = 0;
00173     }
00174 };
00175 
00176 inline define_array<> make_define_array()
00177 {
00178     return define_array<>();
00179 }
00180 
00181 template <typename... Args>
00182 inline define_array<Args...> make_define_array(Args&... args)
00183 {
00184     return define_array<Args...>(args...);
00185 }
00186 
00187 }  // namespace type
00188 /// @cond
00189 }  // MSGPACK_API_VERSION_NAMESPACE(v1)
00190 /// @endcond
00191 }  // namespace msgpack
00192 
00193 #endif // MSGPACK_CPP11_DEFINE_ARRAY_HPP
00194