messagepack implementation for embedded systems (mbed / arduino)
Dependents: hello_message_pack
map.hpp
00001 // 00002 // MessagePack for C++ static resolution routine 00003 // 00004 // Copyright (C) 2008-2015 FURUHASHI Sadayuki 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_TYPE_MAP_HPP 00011 #define MSGPACK_TYPE_MAP_HPP 00012 00013 #include "msgpack/versioning.hpp" 00014 #include "msgpack/object_fwd.hpp" 00015 #include "msgpack/adaptor/check_container_size.hpp" 00016 00017 #include <map> 00018 #include <vector> 00019 #include <algorithm> 00020 00021 namespace msgpack { 00022 00023 /// @cond 00024 MSGPACK_API_VERSION_NAMESPACE(v1) { 00025 /// @endcond 00026 00027 namespace type { 00028 00029 template <typename K, typename V, typename Compare = std::less<K>, typename Alloc = std::allocator<std::pair<K, V> > > 00030 class assoc_vector : public std::vector< std::pair<K, V>, Alloc > { 00031 #if !defined(MSGPACK_USE_CPP03) 00032 using std::vector<std::pair<K, V>, Alloc>::vector; 00033 #endif // !defined(MSGPACK_USE_CPP03) 00034 }; 00035 00036 namespace detail { 00037 template <typename K, typename V, typename Compare, typename Alloc> 00038 struct pair_first_less { 00039 bool operator() (const std::pair<K, V>& x, const std::pair<K, V>& y) const 00040 { return Compare()(x.first, y.first); } 00041 }; 00042 } 00043 00044 } //namespace type 00045 00046 namespace adaptor { 00047 00048 #if !defined(MSGPACK_USE_CPP03) 00049 00050 template <typename K, typename V, typename Compare, typename Alloc> 00051 struct as< 00052 type::assoc_vector<K, V, Compare, Alloc>, 00053 typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> { 00054 type::assoc_vector<K, V, Compare, Alloc> operator()(msgpack::object const& o) const { 00055 if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } 00056 type::assoc_vector<K, V, Compare, Alloc> v; 00057 v.reserve(o.via.map.size); 00058 msgpack::object_kv* p = o.via.map.ptr; 00059 msgpack::object_kv* const pend = o.via.map.ptr + o.via.map.size; 00060 for (; p < pend; ++p) { 00061 v.emplace_back(p->key.as<K>(), p->val.as<V>()); 00062 } 00063 std::sort(v.begin(), v.end(), type::detail::pair_first_less<K, V, Compare, Alloc>()); 00064 return v; 00065 } 00066 }; 00067 00068 #endif // !defined(MSGPACK_USE_CPP03) 00069 00070 template <typename K, typename V, typename Compare, typename Alloc> 00071 struct convert<type::assoc_vector<K, V, Compare, Alloc> > { 00072 msgpack::object const& operator()(msgpack::object const& o, type::assoc_vector<K, V, Compare, Alloc>& v) const { 00073 if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } 00074 v.resize(o.via.map.size); 00075 msgpack::object_kv* p = o.via.map.ptr; 00076 msgpack::object_kv* const pend = o.via.map.ptr + o.via.map.size; 00077 std::pair<K, V>* it(&v.front()); 00078 for (; p < pend; ++p, ++it) { 00079 p->key.convert(it->first); 00080 p->val.convert(it->second); 00081 } 00082 std::sort(v.begin(), v.end(), type::detail::pair_first_less<K, V, Compare, Alloc>()); 00083 return o; 00084 } 00085 }; 00086 00087 template <typename K, typename V, typename Compare, typename Alloc> 00088 struct pack<type::assoc_vector<K, V, Compare, Alloc> > { 00089 template <typename Stream> 00090 msgpack::packer<Stream> & operator()(msgpack::packer<Stream> & o, const type::assoc_vector<K, V, Compare, Alloc>& v) const { 00091 uint32_t size = checked_get_container_size(v.size()); 00092 o.pack_map(size); 00093 for (typename type::assoc_vector<K, V, Compare, Alloc>::const_iterator it(v.begin()), it_end(v.end()); 00094 it != it_end; ++it) { 00095 o.pack(it->first); 00096 o.pack(it->second); 00097 } 00098 return o; 00099 } 00100 }; 00101 00102 template <typename K, typename V, typename Compare, typename Alloc> 00103 struct object_with_zone<type::assoc_vector<K, V, Compare, Alloc> > { 00104 void operator()(msgpack::object::with_zone& o, const type::assoc_vector<K, V, Compare, Alloc>& v) const { 00105 o.type = msgpack::type::MAP; 00106 if (v.empty()) { 00107 o.via.map.ptr = nullptr; 00108 o.via.map.size = 0; 00109 } 00110 else { 00111 uint32_t size = checked_get_container_size(v.size()); 00112 msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size)); 00113 msgpack::object_kv* const pend = p + size; 00114 o.via.map.ptr = p; 00115 o.via.map.size = size; 00116 typename type::assoc_vector<K, V, Compare, Alloc>::const_iterator it(v.begin()); 00117 do { 00118 p->key = msgpack::object(it->first, o.zone); 00119 p->val = msgpack::object(it->second, o.zone); 00120 ++p; 00121 ++it; 00122 } while(p < pend); 00123 } 00124 } 00125 }; 00126 00127 #if !defined(MSGPACK_USE_CPP03) 00128 00129 template <typename K, typename V, typename Compare, typename Alloc> 00130 struct as< 00131 std::map<K, V, Compare, Alloc>, 00132 typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> { 00133 std::map<K, V, Compare, Alloc> operator()(msgpack::object const& o) const { 00134 if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } 00135 msgpack::object_kv* p(o.via.map.ptr); 00136 msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); 00137 std::map<K, V, Compare, Alloc> v; 00138 for (; p != pend; ++p) { 00139 v.emplace(p->key.as<K>(), p->val.as<V>()); 00140 } 00141 return v; 00142 } 00143 }; 00144 00145 #endif // !defined(MSGPACK_USE_CPP03) 00146 00147 template <typename K, typename V, typename Compare, typename Alloc> 00148 struct convert<std::map<K, V, Compare, Alloc> > { 00149 msgpack::object const& operator()(msgpack::object const& o, std::map<K, V, Compare, Alloc>& v) const { 00150 if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } 00151 msgpack::object_kv* p(o.via.map.ptr); 00152 msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); 00153 std::map<K, V, Compare, Alloc> tmp; 00154 for (; p != pend; ++p) { 00155 K key; 00156 p->key.convert(key); 00157 #if __cplusplus >= 201103L 00158 p->val.convert(tmp[std::move(key)]); 00159 #else 00160 p->val.convert(tmp[key]); 00161 #endif 00162 } 00163 #if __cplusplus >= 201103L 00164 v = std::move(tmp); 00165 #else 00166 tmp.swap(v); 00167 #endif 00168 return o; 00169 } 00170 }; 00171 00172 template <typename K, typename V, typename Compare, typename Alloc> 00173 struct pack<std::map<K, V, Compare, Alloc> > { 00174 template <typename Stream> 00175 msgpack::packer<Stream> & operator()(msgpack::packer<Stream> & o, const std::map<K, V, Compare, Alloc>& v) const { 00176 uint32_t size = checked_get_container_size(v.size()); 00177 o.pack_map(size); 00178 for (typename std::map<K, V, Compare, Alloc>::const_iterator it(v.begin()), it_end(v.end()); 00179 it != it_end; ++it) { 00180 o.pack(it->first); 00181 o.pack(it->second); 00182 } 00183 return o; 00184 } 00185 }; 00186 00187 template <typename K, typename V, typename Compare, typename Alloc> 00188 struct object_with_zone<std::map<K, V, Compare, Alloc> > { 00189 void operator()(msgpack::object::with_zone& o, const std::map<K, V, Compare, Alloc>& v) const { 00190 o.type = msgpack::type::MAP; 00191 if (v.empty()) { 00192 o.via.map.ptr = nullptr; 00193 o.via.map.size = 0; 00194 } 00195 else { 00196 uint32_t size = checked_get_container_size(v.size()); 00197 msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size)); 00198 msgpack::object_kv* const pend = p + size; 00199 o.via.map.ptr = p; 00200 o.via.map.size = size; 00201 typename std::map<K, V, Compare, Alloc>::const_iterator it(v.begin()); 00202 do { 00203 p->key = msgpack::object(it->first, o.zone); 00204 p->val = msgpack::object(it->second, o.zone); 00205 ++p; 00206 ++it; 00207 } while(p < pend); 00208 } 00209 } 00210 }; 00211 00212 #if !defined(MSGPACK_USE_CPP03) 00213 00214 template <typename K, typename V, typename Compare, typename Alloc> 00215 struct as< 00216 std::multimap<K, V, Compare, Alloc>, 00217 typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> { 00218 std::multimap<K, V, Compare, Alloc> operator()(msgpack::object const& o) const { 00219 if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } 00220 msgpack::object_kv* p(o.via.map.ptr); 00221 msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); 00222 std::multimap<K, V, Compare, Alloc> v; 00223 for (; p != pend; ++p) { 00224 v.emplace(p->key.as<K>(), p->val.as<V>()); 00225 } 00226 return v; 00227 } 00228 }; 00229 00230 #endif // !defined(MSGPACK_USE_CPP03) 00231 00232 template <typename K, typename V, typename Compare, typename Alloc> 00233 struct convert<std::multimap<K, V, Compare, Alloc> > { 00234 msgpack::object const& operator()(msgpack::object const& o, std::multimap<K, V, Compare, Alloc>& v) const { 00235 if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } 00236 msgpack::object_kv* p(o.via.map.ptr); 00237 msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); 00238 std::multimap<K, V, Compare, Alloc> tmp; 00239 for (; p != pend; ++p) { 00240 std::pair<K, V> value; 00241 p->key.convert(value.first); 00242 p->val.convert(value.second); 00243 #if __cplusplus >= 201103L 00244 tmp.insert(std::move(value)); 00245 #else 00246 tmp.insert(value); 00247 #endif 00248 } 00249 #if __cplusplus >= 201103L 00250 v = std::move(tmp); 00251 #else 00252 tmp.swap(v); 00253 #endif 00254 return o; 00255 } 00256 }; 00257 00258 template <typename K, typename V, typename Compare, typename Alloc> 00259 struct pack<std::multimap<K, V, Compare, Alloc> > { 00260 template <typename Stream> 00261 msgpack::packer<Stream> & operator()(msgpack::packer<Stream> & o, const std::multimap<K, V, Compare, Alloc>& v) const { 00262 uint32_t size = checked_get_container_size(v.size()); 00263 o.pack_map(size); 00264 for (typename std::multimap<K, V, Compare, Alloc>::const_iterator it(v.begin()), it_end(v.end()); 00265 it != it_end; ++it) { 00266 o.pack(it->first); 00267 o.pack(it->second); 00268 } 00269 return o; 00270 } 00271 }; 00272 00273 template <typename K, typename V, typename Compare, typename Alloc> 00274 struct object_with_zone<std::multimap<K, V, Compare, Alloc> > { 00275 void operator()(msgpack::object::with_zone& o, const std::multimap<K, V, Compare, Alloc>& v) const { 00276 o.type = msgpack::type::MAP; 00277 if (v.empty()) { 00278 o.via.map.ptr = nullptr; 00279 o.via.map.size = 0; 00280 } 00281 else { 00282 uint32_t size = checked_get_container_size(v.size()); 00283 msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size)); 00284 msgpack::object_kv* const pend = p + size; 00285 o.via.map.ptr = p; 00286 o.via.map.size = size; 00287 typename std::multimap<K, V, Compare, Alloc>::const_iterator it(v.begin()); 00288 do { 00289 p->key = msgpack::object(it->first, o.zone); 00290 p->val = msgpack::object(it->second, o.zone); 00291 ++p; 00292 ++it; 00293 } while(p < pend); 00294 } 00295 } 00296 }; 00297 00298 } // namespace adaptor 00299 00300 /// @cond 00301 } // MSGPACK_API_VERSION_NAMESPACE(v1) 00302 /// @endcond 00303 00304 } // namespace msgpack 00305 00306 #endif // MSGPACK_TYPE_MAP_HPP
Generated on Tue Jul 12 2022 22:51:46 by 1.7.2