1// 2// MessagePack for C++ static resolution routine 3// 4// Copyright (C) 2008-2015 FURUHASHI Sadayuki and KONDO Takatoshi 5// 6// Distributed under the Boost Software License, Version 1.0. 7// (See accompanying file LICENSE_1_0.txt or copy at 8// http://www.boost.org/LICENSE_1_0.txt) 9// 10#ifndef MSGPACK_CPP11_TUPLE_HPP 11#define MSGPACK_CPP11_TUPLE_HPP 12 13#include "msgpack/versioning.hpp" 14#include "msgpack/adaptor/adaptor_base.hpp" 15#include "msgpack/adaptor/check_container_size.hpp" 16#include "msgpack/meta.hpp" 17 18#include <tuple> 19 20namespace msgpack { 21 22/// @cond 23MSGPACK_API_VERSION_NAMESPACE(v1) { 24/// @endcond 25 26// --- Pack from tuple to packer stream --- 27template <typename Stream, typename Tuple, std::size_t N> 28struct StdTuplePacker { 29 static void pack( 30 msgpack::packer<Stream>& o, 31 const Tuple& v) { 32 StdTuplePacker<Stream, Tuple, N-1>::pack(o, v); 33 o.pack(std::get<N-1>(v)); 34 } 35}; 36 37template <typename Stream, typename Tuple> 38struct StdTuplePacker<Stream, Tuple, 0> { 39 static void pack ( 40 msgpack::packer<Stream>&, 41 const Tuple&) { 42 } 43}; 44 45namespace adaptor { 46 47template <typename... Args> 48struct pack<std::tuple<Args...>> { 49 template <typename Stream> 50 msgpack::packer<Stream>& operator()( 51 msgpack::packer<Stream>& o, 52 const std::tuple<Args...>& v) const { 53 uint32_t size = checked_get_container_size(sizeof...(Args)); 54 o.pack_array(size); 55 StdTuplePacker<Stream, decltype(v), sizeof...(Args)>::pack(o, v); 56 return o; 57 } 58}; 59 60} // namespace adaptor 61 62// --- Convert from tuple to object --- 63 64template <typename... Args> 65struct StdTupleAs; 66 67template <typename T, typename... Args> 68struct StdTupleAsImpl { 69 static std::tuple<T, Args...> as(msgpack::object const& o) { 70 return std::tuple_cat( 71 std::make_tuple(o.via.array.ptr[o.via.array.size - sizeof...(Args) - 1].as<T>()), 72 StdTupleAs<Args...>::as(o)); 73 } 74}; 75 76template <typename... Args> 77struct StdTupleAs { 78 static std::tuple<Args...> as(msgpack::object const& o) { 79 return StdTupleAsImpl<Args...>::as(o); 80 } 81}; 82 83template <> 84struct StdTupleAs<> { 85 static std::tuple<> as (msgpack::object const&) { 86 return std::tuple<>(); 87 } 88}; 89 90template <typename Tuple, std::size_t N> 91struct StdTupleConverter { 92 static void convert( 93 msgpack::object const& o, 94 Tuple& v) { 95 StdTupleConverter<Tuple, N-1>::convert(o, v); 96 o.via.array.ptr[N-1].convert<typename std::remove_reference<decltype(std::get<N-1>(v))>::type>(std::get<N-1>(v)); 97 } 98}; 99 100template <typename Tuple> 101struct StdTupleConverter<Tuple, 0> { 102 static void convert ( 103 msgpack::object const&, 104 Tuple&) { 105 } 106}; 107 108namespace adaptor { 109 110template <typename... Args> 111struct as<std::tuple<Args...>, typename std::enable_if<msgpack::all_of<msgpack::has_as, Args...>::value>::type> { 112 std::tuple<Args...> operator()( 113 msgpack::object const& o) const { 114 if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } 115 if (o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } 116 return StdTupleAs<Args...>::as(o); 117 } 118}; 119 120template <typename... Args> 121struct convert<std::tuple<Args...>> { 122 msgpack::object const& operator()( 123 msgpack::object const& o, 124 std::tuple<Args...>& v) const { 125 if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } 126 if(o.via.array.size < sizeof...(Args)) { throw msgpack::type_error(); } 127 StdTupleConverter<decltype(v), sizeof...(Args)>::convert(o, v); 128 return o; 129 } 130}; 131 132} // namespace adaptor 133 134// --- Convert from tuple to object with zone --- 135template <typename Tuple, std::size_t N> 136struct StdTupleToObjectWithZone { 137 static void convert( 138 msgpack::object::with_zone& o, 139 const Tuple& v) { 140 StdTupleToObjectWithZone<Tuple, N-1>::convert(o, v); 141 o.via.array.ptr[N-1] = msgpack::object(std::get<N-1>(v), o.zone); 142 } 143}; 144 145template <typename Tuple> 146struct StdTupleToObjectWithZone<Tuple, 0> { 147 static void convert ( 148 msgpack::object::with_zone&, 149 const Tuple&) { 150 } 151}; 152 153namespace adaptor { 154 155template <typename... Args> 156struct object_with_zone<std::tuple<Args...>> { 157 void operator()( 158 msgpack::object::with_zone& o, 159 std::tuple<Args...> const& v) const { 160 uint32_t size = checked_get_container_size(sizeof...(Args)); 161 o.type = msgpack::type::ARRAY; 162 o.via.array.ptr = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size)); 163 o.via.array.size = size; 164 StdTupleToObjectWithZone<decltype(v), sizeof...(Args)>::convert(o, v); 165 } 166}; 167 168} // namespace adaptor 169 170/// @cond 171} // MSGPACK_API_VERSION_NAMESPACE(v1) 172/// @endcond 173 174} // namespace msgpack 175 176#endif // MSGPACK_CPP11_TUPLE_HPP 177