1// 2// MessagePack for C++ static resolution routine 3// 4// Copyright (C) 2008-2009 FURUHASHI Sadayuki 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_TYPE_ARRAY_REF_HPP 11#define MSGPACK_TYPE_ARRAY_REF_HPP 12 13#include "msgpack/versioning.hpp" 14#include "msgpack/adaptor/adaptor_base.hpp" 15#include "msgpack/adaptor/check_container_size.hpp" 16#include <cstring> 17#include <string> 18 19namespace msgpack { 20 21/// @cond 22MSGPACK_API_VERSION_NAMESPACE(v1) { 23/// @endcond 24 25namespace type { 26 27template <typename T> 28struct array_ref { 29 array_ref() : data(nullptr) {} 30 array_ref(T& t) : data(&t) {} 31 32 T* data; 33 34 template <typename U> 35 bool operator==(array_ref<U> const& t) const { 36 return *data == *t.data; 37 } 38 template <typename U> 39 bool operator!=(array_ref<U> const& t) const { 40 return !(*data == *t.data); 41 } 42 template <typename U> 43 bool operator< (array_ref<U> const& t) const 44 { 45 return *data < *t.data; 46 } 47 template <typename U> 48 bool operator> (array_ref<U> const& t) const 49 { 50 return *t.data < *data; 51 } 52 template <typename U> 53 bool operator<= (array_ref<U> const& t) const 54 { 55 return !(*t.data < *data); 56 } 57 template <typename U> 58 bool operator>= (array_ref<U> const& t) const 59 { 60 return !(*data < *t.data); 61 } 62}; 63 64template <typename T> 65inline array_ref<T const> make_array_ref(T const& t) { 66 return array_ref<T const>(t); 67} 68 69template <typename T> 70inline array_ref<T> make_array_ref(T& t) { 71 return array_ref<T>(t); 72} 73 74 75} // namespace type 76 77namespace adaptor { 78 79template <typename T> 80struct convert<msgpack::type::array_ref<T> > { 81 msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref<T>& v) const { 82 if (!v.data) { throw msgpack::type_error(); } 83 if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } 84 if (v.data->size() < o.via.bin.size) { throw msgpack::type_error(); } 85 if (o.via.array.size > 0) { 86 msgpack::object* p = o.via.array.ptr; 87 msgpack::object* const pend = o.via.array.ptr + o.via.array.size; 88 typename T::iterator it = v.data->begin(); 89 do { 90 p->convert(*it); 91 ++p; 92 ++it; 93 } while(p < pend); 94 } 95 return o; 96 } 97}; 98 99template <typename T> 100struct convert<msgpack::type::array_ref<std::vector<T> > > { 101 msgpack::object const& operator()(msgpack::object const& o, msgpack::type::array_ref<std::vector<T> >& v) const { 102 if (!v.data) { throw msgpack::type_error(); } 103 if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } 104 v.data->resize(o.via.bin.size); 105 if (o.via.array.size > 0) { 106 msgpack::object* p = o.via.array.ptr; 107 msgpack::object* const pend = o.via.array.ptr + o.via.array.size; 108 typename std::vector<T>::iterator it = v.data->begin(); 109 do { 110 p->convert(*it); 111 ++p; 112 ++it; 113 } while(p < pend); 114 } 115 return o; 116 } 117}; 118 119template <typename T> 120struct pack<msgpack::type::array_ref<T> > { 121 template <typename Stream> 122 msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const msgpack::type::array_ref<T>& v) const { 123 if (!v.data) { throw msgpack::type_error(); } 124 uint32_t size = checked_get_container_size(v.data->size()); 125 o.pack_array(size); 126 for (typename T::const_iterator it(v.data->begin()), it_end(v.data->end()); 127 it != it_end; ++it) { 128 o.pack(*it); 129 } 130 return o; 131 } 132}; 133 134template <typename T> 135struct object_with_zone<msgpack::type::array_ref<T> > { 136 void operator()(msgpack::object::with_zone& o, const msgpack::type::array_ref<T>& v) const { 137 if (!v.data) { throw msgpack::type_error(); } 138 o.type = msgpack::type::ARRAY; 139 if (v.data->empty()) { 140 o.via.array.ptr = nullptr; 141 o.via.array.size = 0; 142 } 143 else { 144 uint32_t size = checked_get_container_size(v.data->size()); 145 msgpack::object* p = static_cast<msgpack::object*>(o.zone.allocate_align(sizeof(msgpack::object)*size)); 146 msgpack::object* const pend = p + size; 147 o.via.array.ptr = p; 148 o.via.array.size = size; 149 typename T::const_iterator it(v.data->begin()); 150 do { 151#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && !defined(__clang__) 152#pragma GCC diagnostic push 153#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 154#endif // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && !defined(__clang__) 155 *p = msgpack::object(*it, o.zone); 156#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && !defined(__clang__) 157#pragma GCC diagnostic pop 158#endif // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && !defined(__clang__) 159 ++p; 160 ++it; 161 } while(p < pend); 162 } 163 } 164}; 165 166} // namespace adaptor 167 168/// @cond 169} // MSGPACK_API_VERSION_NAMESPACE(v1) 170/// @endcond 171 172} // namespace msgpack 173 174#endif // MSGPACK_TYPE_ARRAY_REF_HPP 175