messagepack implementation for embedded systems (mbed / arduino)

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers map.hpp Source File

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