map.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. //
  2. // MessagePack for C++ static resolution routine
  3. //
  4. // Copyright (C) 2008-2016 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_V1_TYPE_MAP_HPP
  11. #define MSGPACK_V1_TYPE_MAP_HPP
  12. #include "msgpack/v1/adaptor/map_decl.hpp"
  13. #include "msgpack/adaptor/adaptor_base.hpp"
  14. #include <map>
  15. #include <vector>
  16. namespace msgpack {
  17. /// @cond
  18. MSGPACK_API_VERSION_NAMESPACE(v1) {
  19. /// @endcond
  20. namespace type {
  21. template <typename K, typename V, typename Compare, typename Alloc>
  22. class assoc_vector : public std::vector< std::pair<K, V>, Alloc > {
  23. #if !defined(MSGPACK_USE_CPP03)
  24. using std::vector<std::pair<K, V>, Alloc>::vector;
  25. #endif // !defined(MSGPACK_USE_CPP03)
  26. };
  27. namespace detail {
  28. template <typename K, typename V, typename Compare, typename Alloc>
  29. struct pair_first_less {
  30. bool operator() (const std::pair<K, V>& x, const std::pair<K, V>& y) const
  31. { return Compare()(x.first, y.first); }
  32. };
  33. }
  34. } //namespace type
  35. namespace adaptor {
  36. #if !defined(MSGPACK_USE_CPP03)
  37. template <typename K, typename V, typename Compare, typename Alloc>
  38. struct as<
  39. type::assoc_vector<K, V, Compare, Alloc>,
  40. typename std::enable_if<msgpack::has_as<K>::value || msgpack::has_as<V>::value>::type> {
  41. type::assoc_vector<K, V, Compare, Alloc> operator()(msgpack::object const& o) const {
  42. if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
  43. type::assoc_vector<K, V, Compare, Alloc> v;
  44. v.reserve(o.via.map.size);
  45. msgpack::object_kv* p = o.via.map.ptr;
  46. msgpack::object_kv* const pend = o.via.map.ptr + o.via.map.size;
  47. for (; p < pend; ++p) {
  48. v.emplace_back(p->key.as<K>(), p->val.as<V>());
  49. }
  50. std::sort(v.begin(), v.end(), type::detail::pair_first_less<K, V, Compare, Alloc>());
  51. return v;
  52. }
  53. };
  54. #endif // !defined(MSGPACK_USE_CPP03)
  55. template <typename K, typename V, typename Compare, typename Alloc>
  56. struct convert<type::assoc_vector<K, V, Compare, Alloc> > {
  57. msgpack::object const& operator()(msgpack::object const& o, type::assoc_vector<K, V, Compare, Alloc>& v) const {
  58. if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
  59. v.resize(o.via.map.size);
  60. if (o.via.map.size != 0) {
  61. msgpack::object_kv* p = o.via.map.ptr;
  62. msgpack::object_kv* const pend = o.via.map.ptr + o.via.map.size;
  63. std::pair<K, V>* it(&v.front());
  64. for (; p < pend; ++p, ++it) {
  65. p->key.convert(it->first);
  66. p->val.convert(it->second);
  67. }
  68. std::sort(v.begin(), v.end(), type::detail::pair_first_less<K, V, Compare, Alloc>());
  69. }
  70. return o;
  71. }
  72. };
  73. template <typename K, typename V, typename Compare, typename Alloc>
  74. struct pack<type::assoc_vector<K, V, Compare, Alloc> > {
  75. template <typename Stream>
  76. msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const type::assoc_vector<K, V, Compare, Alloc>& v) const {
  77. uint32_t size = checked_get_container_size(v.size());
  78. o.pack_map(size);
  79. for (typename type::assoc_vector<K, V, Compare, Alloc>::const_iterator it(v.begin()), it_end(v.end());
  80. it != it_end; ++it) {
  81. o.pack(it->first);
  82. o.pack(it->second);
  83. }
  84. return o;
  85. }
  86. };
  87. template <typename K, typename V, typename Compare, typename Alloc>
  88. struct object_with_zone<type::assoc_vector<K, V, Compare, Alloc> > {
  89. void operator()(msgpack::object::with_zone& o, const type::assoc_vector<K, V, Compare, Alloc>& v) const {
  90. o.type = msgpack::type::MAP;
  91. if (v.empty()) {
  92. o.via.map.ptr = MSGPACK_NULLPTR;
  93. o.via.map.size = 0;
  94. }
  95. else {
  96. uint32_t size = checked_get_container_size(v.size());
  97. msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv)));
  98. msgpack::object_kv* const pend = p + size;
  99. o.via.map.ptr = p;
  100. o.via.map.size = size;
  101. typename type::assoc_vector<K, V, Compare, Alloc>::const_iterator it(v.begin());
  102. do {
  103. p->key = msgpack::object(it->first, o.zone);
  104. p->val = msgpack::object(it->second, o.zone);
  105. ++p;
  106. ++it;
  107. } while(p < pend);
  108. }
  109. }
  110. };
  111. #if !defined(MSGPACK_USE_CPP03)
  112. template <typename K, typename V, typename Compare, typename Alloc>
  113. struct as<
  114. std::map<K, V, Compare, Alloc>,
  115. typename std::enable_if<msgpack::has_as<K>::value || msgpack::has_as<V>::value>::type> {
  116. std::map<K, V, Compare, Alloc> operator()(msgpack::object const& o) const {
  117. if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
  118. msgpack::object_kv* p(o.via.map.ptr);
  119. msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
  120. std::map<K, V, Compare, Alloc> v;
  121. for (; p != pend; ++p) {
  122. v.emplace(p->key.as<K>(), p->val.as<V>());
  123. }
  124. return v;
  125. }
  126. };
  127. #endif // !defined(MSGPACK_USE_CPP03)
  128. template <typename K, typename V, typename Compare, typename Alloc>
  129. struct convert<std::map<K, V, Compare, Alloc> > {
  130. msgpack::object const& operator()(msgpack::object const& o, std::map<K, V, Compare, Alloc>& v) const {
  131. if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
  132. msgpack::object_kv* p(o.via.map.ptr);
  133. msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
  134. std::map<K, V, Compare, Alloc> tmp;
  135. for (; p != pend; ++p) {
  136. K key;
  137. p->key.convert(key);
  138. #if __cplusplus >= 201103L
  139. p->val.convert(tmp[std::move(key)]);
  140. #else
  141. p->val.convert(tmp[key]);
  142. #endif
  143. }
  144. #if __cplusplus >= 201103L
  145. v = std::move(tmp);
  146. #else
  147. tmp.swap(v);
  148. #endif
  149. return o;
  150. }
  151. };
  152. template <typename K, typename V, typename Compare, typename Alloc>
  153. struct pack<std::map<K, V, Compare, Alloc> > {
  154. template <typename Stream>
  155. msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::map<K, V, Compare, Alloc>& v) const {
  156. uint32_t size = checked_get_container_size(v.size());
  157. o.pack_map(size);
  158. for (typename std::map<K, V, Compare, Alloc>::const_iterator it(v.begin()), it_end(v.end());
  159. it != it_end; ++it) {
  160. o.pack(it->first);
  161. o.pack(it->second);
  162. }
  163. return o;
  164. }
  165. };
  166. template <typename K, typename V, typename Compare, typename Alloc>
  167. struct object_with_zone<std::map<K, V, Compare, Alloc> > {
  168. void operator()(msgpack::object::with_zone& o, const std::map<K, V, Compare, Alloc>& v) const {
  169. o.type = msgpack::type::MAP;
  170. if (v.empty()) {
  171. o.via.map.ptr = MSGPACK_NULLPTR;
  172. o.via.map.size = 0;
  173. }
  174. else {
  175. uint32_t size = checked_get_container_size(v.size());
  176. msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv)));
  177. msgpack::object_kv* const pend = p + size;
  178. o.via.map.ptr = p;
  179. o.via.map.size = size;
  180. typename std::map<K, V, Compare, Alloc>::const_iterator it(v.begin());
  181. do {
  182. #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__clang__)
  183. #pragma GCC diagnostic push
  184. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  185. #endif // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__clang__)
  186. p->key = msgpack::object(it->first, o.zone);
  187. p->val = msgpack::object(it->second, o.zone);
  188. #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__clang__)
  189. #pragma GCC diagnostic pop
  190. #endif // (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__clang__)
  191. ++p;
  192. ++it;
  193. } while(p < pend);
  194. }
  195. }
  196. };
  197. #if !defined(MSGPACK_USE_CPP03)
  198. template <typename K, typename V, typename Compare, typename Alloc>
  199. struct as<
  200. std::multimap<K, V, Compare, Alloc>,
  201. typename std::enable_if<msgpack::has_as<K>::value || msgpack::has_as<V>::value>::type> {
  202. std::multimap<K, V, Compare, Alloc> operator()(msgpack::object const& o) const {
  203. if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
  204. msgpack::object_kv* p(o.via.map.ptr);
  205. msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
  206. std::multimap<K, V, Compare, Alloc> v;
  207. for (; p != pend; ++p) {
  208. v.emplace(p->key.as<K>(), p->val.as<V>());
  209. }
  210. return v;
  211. }
  212. };
  213. #endif // !defined(MSGPACK_USE_CPP03)
  214. template <typename K, typename V, typename Compare, typename Alloc>
  215. struct convert<std::multimap<K, V, Compare, Alloc> > {
  216. msgpack::object const& operator()(msgpack::object const& o, std::multimap<K, V, Compare, Alloc>& v) const {
  217. if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
  218. msgpack::object_kv* p(o.via.map.ptr);
  219. msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
  220. std::multimap<K, V, Compare, Alloc> tmp;
  221. for (; p != pend; ++p) {
  222. std::pair<K, V> value;
  223. p->key.convert(value.first);
  224. p->val.convert(value.second);
  225. #if __cplusplus >= 201103L
  226. tmp.insert(std::move(value));
  227. #else
  228. tmp.insert(value);
  229. #endif
  230. }
  231. #if __cplusplus >= 201103L
  232. v = std::move(tmp);
  233. #else
  234. tmp.swap(v);
  235. #endif
  236. return o;
  237. }
  238. };
  239. template <typename K, typename V, typename Compare, typename Alloc>
  240. struct pack<std::multimap<K, V, Compare, Alloc> > {
  241. template <typename Stream>
  242. msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::multimap<K, V, Compare, Alloc>& v) const {
  243. uint32_t size = checked_get_container_size(v.size());
  244. o.pack_map(size);
  245. for (typename std::multimap<K, V, Compare, Alloc>::const_iterator it(v.begin()), it_end(v.end());
  246. it != it_end; ++it) {
  247. o.pack(it->first);
  248. o.pack(it->second);
  249. }
  250. return o;
  251. }
  252. };
  253. template <typename K, typename V, typename Compare, typename Alloc>
  254. struct object_with_zone<std::multimap<K, V, Compare, Alloc> > {
  255. void operator()(msgpack::object::with_zone& o, const std::multimap<K, V, Compare, Alloc>& v) const {
  256. o.type = msgpack::type::MAP;
  257. if (v.empty()) {
  258. o.via.map.ptr = MSGPACK_NULLPTR;
  259. o.via.map.size = 0;
  260. }
  261. else {
  262. uint32_t size = checked_get_container_size(v.size());
  263. msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size, MSGPACK_ZONE_ALIGNOF(msgpack::object_kv)));
  264. msgpack::object_kv* const pend = p + size;
  265. o.via.map.ptr = p;
  266. o.via.map.size = size;
  267. typename std::multimap<K, V, Compare, Alloc>::const_iterator it(v.begin());
  268. do {
  269. p->key = msgpack::object(it->first, o.zone);
  270. p->val = msgpack::object(it->second, o.zone);
  271. ++p;
  272. ++it;
  273. } while(p < pend);
  274. }
  275. }
  276. };
  277. } // namespace adaptor
  278. /// @cond
  279. } // MSGPACK_API_VERSION_NAMESPACE(v1)
  280. /// @endcond
  281. } // namespace msgpack
  282. #endif // MSGPACK_V1_TYPE_MAP_HPP