messagepack implementation for embedded systems (mbed / arduino)

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cpp11_msgpack_tuple.hpp Source File

cpp11_msgpack_tuple.hpp

00001 //
00002 // MessagePack for C++ static resolution routine
00003 //
00004 // Copyright (C) 2008-2015 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_MSGPACK_TUPLE_HPP
00011 #define MSGPACK_CPP11_MSGPACK_TUPLE_HPP
00012 
00013 #include "msgpack/versioning.hpp"
00014 #include "msgpack/object_fwd.hpp"
00015 #include "msgpack/meta.hpp"
00016 
00017 #include <tuple>
00018 
00019 namespace msgpack {
00020 
00021 /// @cond
00022 MSGPACK_API_VERSION_NAMESPACE(v1) {
00023 /// @endcond
00024 
00025 namespace type {
00026     // tuple
00027     using std::get;
00028     using std::tuple_size;
00029     using std::tuple_element;
00030     using std::uses_allocator;
00031     using std::ignore;
00032     using std::swap;
00033 
00034     template< class... Types >
00035     class tuple : public std::tuple<Types...> {
00036     public:
00037         using base = std::tuple<Types...>;
00038 
00039         using base::base;
00040 
00041         tuple() = default;
00042         tuple(tuple const&) = default;
00043         tuple(tuple&&) = default;
00044 
00045         template<typename... OtherTypes>
00046         tuple(tuple<OtherTypes...> const& other):base(static_cast<std::tuple<OtherTypes...> const&>(other)) {}
00047         template<typename... OtherTypes>
00048         tuple(tuple<OtherTypes...> && other):base(static_cast<std::tuple<OtherTypes...> &&>(other)) {}
00049 
00050         tuple& operator=(tuple const&) = default;
00051         tuple& operator=(tuple&&) = default;
00052 
00053         template<typename... OtherTypes>
00054         tuple& operator=(tuple<OtherTypes...> const& other) {
00055             *static_cast<base*>(this) = static_cast<std::tuple<OtherTypes...> const&>(other);
00056             return *this;
00057         }
00058         template<typename... OtherTypes>
00059         tuple& operator=(tuple<OtherTypes...> && other) {
00060             *static_cast<base*>(this) = static_cast<std::tuple<OtherTypes...> &&>(other);
00061             return *this;
00062         }
00063 
00064         template< std::size_t I>
00065         typename tuple_element<I, base >::type&
00066         get() & { return std::get<I>(*this); }
00067 
00068         template< std::size_t I>
00069         typename tuple_element<I, base >::type const&
00070         get() const& { return std::get<I>(*this); }
00071 
00072         template< std::size_t I>
00073         typename tuple_element<I, base >::type&&
00074         get() && { return std::get<I>(*this); }
00075     };
00076 
00077     template <class... Args>
00078     inline tuple<Args...> make_tuple(Args&&... args) {
00079         return tuple<Args...>(args...);
00080     }
00081 
00082     template<class... Args>
00083     inline tuple<Args&&...> forward_as_tuple (Args&&... args) noexcept {
00084         return tuple<Args&&...>(std::forward<Args>(args)...);
00085     }
00086 
00087     template <class... Tuples>
00088     inline auto tuple_cat(Tuples&&... args) ->
00089         decltype(
00090             std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...)
00091         ) {
00092         return std::tuple_cat(std::forward<typename std::remove_reference<Tuples>::type::base>(args)...);
00093     }
00094     template <class... Args>
00095     inline tuple<Args&...> tie(Args&... args) {
00096         return tuple<Args&...>(args...);
00097     }
00098 } // namespace type
00099 
00100 // --- Pack from tuple to packer stream ---
00101 template <typename Stream, typename Tuple, std::size_t N>
00102 struct MsgpackTuplePacker {
00103     static void pack(
00104         msgpack::packer<Stream> & o,
00105         const Tuple& v) {
00106         MsgpackTuplePacker<Stream, Tuple, N-1>::pack(o, v);
00107         o.pack(type::get<N-1>(v));
00108     }
00109 };
00110 
00111 template <typename Stream, typename Tuple>
00112 struct MsgpackTuplePacker<Stream, Tuple, 1> {
00113     static void pack (
00114         msgpack::packer<Stream> & o,
00115         const Tuple& v) {
00116         o.pack(type::get<0>(v));
00117     }
00118 };
00119 
00120 template <typename Stream, typename Tuple>
00121 struct MsgpackTuplePacker<Stream, Tuple, 0> {
00122     static void pack (
00123         msgpack::packer<Stream> &,
00124         const Tuple&) {
00125     }
00126 };
00127 
00128 namespace adaptor {
00129 
00130 template <typename... Args>
00131 struct pack<msgpack::type::tuple<Args...>> {
00132     template <typename Stream>
00133     msgpack::packer<Stream> & operator()(
00134         msgpack::packer<Stream> & o,
00135         const msgpack::type::tuple<Args...>& v) const {
00136         o.pack_array(sizeof...(Args));
00137         MsgpackTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v);
00138         return o;
00139     }
00140 };
00141 
00142 } // namespace adaptor
00143 
00144 // --- Convert from tuple to object ---
00145 
00146 template <typename... Args>
00147 struct MsgpackTupleAs;
00148 
00149 template <typename T, typename... Args>
00150 struct MsgpackTupleAsImpl {
00151     static msgpack::type::tuple<T, Args...> as(msgpack::object const& o) {
00152         return msgpack::type::tuple_cat(
00153             msgpack::type::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()),
00154             MsgpackTupleAs<Args...>::as(o));
00155     }
00156 };
00157 
00158 template <typename... Args>
00159 struct MsgpackTupleAs {
00160     static msgpack::type::tuple<Args...> as(msgpack::object const& o) {
00161         return MsgpackTupleAsImpl<Args...>::as(o);
00162     }
00163 };
00164 
00165 template <>
00166 struct MsgpackTupleAs<> {
00167     static msgpack::type::tuple<> as (msgpack::object const&) {
00168         return msgpack::type::tuple<>();
00169     }
00170 };
00171 
00172 template <typename Tuple, std::size_t N>
00173 struct MsgpackTupleConverter {
00174     static void convert(
00175         msgpack::object const& o,
00176         Tuple& v) {
00177         MsgpackTupleConverter<Tuple, N-1>::convert(o, v);
00178         o.via.array.ptr[N-1].convert<typename std::remove_reference<decltype(type::get<N-1>(v))>::type>(type::get<N-1>(v));
00179     }
00180 };
00181 
00182 template <typename Tuple>
00183 struct MsgpackTupleConverter<Tuple, 1> {
00184     static void convert (
00185         msgpack::object const& o,
00186         Tuple& v) {
00187         o.via.array.ptr[0].convert<typename std::remove_reference<decltype(type::get<0>(v))>::type>(type::get<0>(v));
00188     }
00189 };
00190 
00191 template <typename Tuple>
00192 struct MsgpackTupleConverter<Tuple, 0> {
00193     static void convert (
00194         msgpack::object const&,
00195         Tuple&) {
00196     }
00197 };
00198 
00199 namespace adaptor {
00200 
00201 template <typename... Args>
00202 struct as<msgpack::type::tuple<Args...>, typename std::enable_if<msgpack::all_of<msgpack::has_as, Args...>::value>::type>  {
00203     msgpack::type::tuple<Args...> operator()(
00204         msgpack::object const& o) const {
00205         if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
00206         if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); }
00207         return MsgpackTupleAs<Args...>::as(o);
00208     }
00209 };
00210 
00211 template <typename... Args>
00212 struct convert<msgpack::type::tuple<Args...>> {
00213     msgpack::object const& operator()(
00214         msgpack::object const& o,
00215         msgpack::type::tuple<Args...>& v) const {
00216         if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
00217         if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); }
00218         MsgpackTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v);
00219         return o;
00220     }
00221 };
00222 
00223 } // namespace adaptor
00224 
00225 // --- Convert from tuple to object with zone ---
00226 template <typename Tuple, std::size_t N>
00227 struct MsgpackTupleToObjectWithZone {
00228     static void convert(
00229         msgpack::object::with_zone& o,
00230         const Tuple& v) {
00231         MsgpackTupleToObjectWithZone<Tuple, N-1>::convert(o, v);
00232         o.via.array.ptr[N-1] = msgpack::object(type::get<N-1>(v), o.zone);
00233     }
00234 };
00235 
00236 template <typename Tuple>
00237 struct MsgpackTupleToObjectWithZone<Tuple, 1> {
00238     static void convert (
00239         msgpack::object::with_zone& o,
00240         const Tuple& v) {
00241         o.via.array.ptr[0] = msgpack::object(type::get<0>(v), o.zone);
00242     }
00243 };
00244 
00245 template <typename Tuple>
00246 struct MsgpackTupleToObjectWithZone<Tuple, 0> {
00247     static void convert (
00248         msgpack::object::with_zone&,
00249         const Tuple&) {
00250     }
00251 };
00252 
00253 namespace adaptor {
00254 
00255 template <typename... Args>
00256     struct object_with_zone<msgpack::type::tuple<Args...>> {
00257     void operator()(
00258         msgpack::object::with_zone& o,
00259         msgpack::type::tuple<Args...> const& v) const {
00260         o.type = msgpack::type::ARRAY;
00261         o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*sizeof...(Args)));
00262         o.via.array.size = sizeof...(Args);
00263         MsgpackTupleToObjectWithZone<decltype(v), sizeof...(Args)>::convert(o, v);
00264     }
00265 };
00266 
00267 }  // namespace adaptor
00268 
00269 /// @cond
00270 }  // MSGPACK_API_VERSION_NAMESPACE(v1)
00271 ///@endcond
00272 
00273 }  // namespace msgpack
00274 
00275 #endif // MSGPACK_CPP11_MSGPACK_TUPLE_HPP
00276