1//
2// MessagePack for C++ static resolution routine
3//
4// Copyright (C) 2008-2015 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_TR1_UNORDERED_MAP_HPP
11#define MSGPACK_TYPE_TR1_UNORDERED_MAP_HPP
12
13#include "msgpack/versioning.hpp"
14#include "msgpack/adaptor/adaptor_base.hpp"
15#include "msgpack/adaptor/check_container_size.hpp"
16
17#if defined(_LIBCPP_VERSION) || (_MSC_VER >= 1700)
18
19#define MSGPACK_HAS_STD_UNORDERED_MAP
20#include <unordered_map>
21#define MSGPACK_STD_TR1 std
22
23#else   // defined(_LIBCPP_VERSION) || (_MSC_VER >= 1700)
24
25#if __GNUC__ >= 4
26
27#define MSGPACK_HAS_STD_TR1_UNORDERED_MAP
28
29#include <tr1/unordered_map>
30#define MSGPACK_STD_TR1 std::tr1
31
32#endif // __GNUC__ >= 4
33
34#endif  // defined(_LIBCPP_VERSION) || (_MSC_VER >= 1700)
35
36#if defined(MSGPACK_STD_TR1)
37
38namespace msgpack {
39
40/// @cond
41MSGPACK_API_VERSION_NAMESPACE(v1) {
42/// @endcond
43
44namespace adaptor {
45
46template <typename K, typename V, typename Hash, typename Pred, typename Alloc>
47struct convert<MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc> > {
48    msgpack::object const& operator()(msgpack::object const& o, MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc>& v) const {
49        if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
50        msgpack::object_kv* p(o.via.map.ptr);
51        msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
52        MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc> tmp;
53        for(; p != pend; ++p) {
54            K key;
55            p->key.convert(key);
56            p->val.convert(tmp[key]);
57        }
58        tmp.swap(v);
59        return o;
60    }
61};
62
63template <typename K, typename V, typename Hash, typename Pred, typename Alloc>
64struct pack<MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc> > {
65    template <typename Stream>
66    msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc>& v) const {
67        uint32_t size = checked_get_container_size(v.size());
68        o.pack_map(size);
69        for(typename MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc>::const_iterator it(v.begin()), it_end(v.end());
70            it != it_end; ++it) {
71            o.pack(it->first);
72            o.pack(it->second);
73        }
74        return o;
75    }
76};
77
78template <typename K, typename V, typename Hash, typename Pred, typename Alloc>
79struct object_with_zone<MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc> > {
80    void operator()(msgpack::object::with_zone& o, const MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc>& v) const {
81        o.type = msgpack::type::MAP;
82        if(v.empty()) {
83            o.via.map.ptr  = nullptr;
84            o.via.map.size = 0;
85        } else {
86            uint32_t size = checked_get_container_size(v.size());
87            msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size));
88            msgpack::object_kv* const pend = p + size;
89            o.via.map.ptr  = p;
90            o.via.map.size = size;
91            typename MSGPACK_STD_TR1::unordered_map<K, V, Hash, Pred, Alloc>::const_iterator it(v.begin());
92            do {
93                p->key = msgpack::object(it->first, o.zone);
94                p->val = msgpack::object(it->second, o.zone);
95                ++p;
96                ++it;
97            } while(p < pend);
98        }
99    }
100};
101
102template <typename K, typename V, typename Hash, typename Pred, typename Alloc>
103struct convert<MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc> > {
104    msgpack::object const& operator()(msgpack::object const& o, MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc>& v) const {
105        if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
106        msgpack::object_kv* p(o.via.map.ptr);
107        msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
108        MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc> tmp;
109        for(; p != pend; ++p) {
110            std::pair<K, V> value;
111            p->key.convert(value.first);
112            p->val.convert(value.second);
113            tmp.insert(value);
114        }
115        tmp.swap(v);
116        return o;
117    }
118};
119
120template <typename K, typename V, typename Hash, typename Pred, typename Alloc>
121struct pack<MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc> > {
122    template <typename Stream>
123    msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc>& v) const {
124        uint32_t size = checked_get_container_size(v.size());
125        o.pack_map(size);
126        for(typename MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc>::const_iterator it(v.begin()), it_end(v.end());
127            it != it_end; ++it) {
128            o.pack(it->first);
129            o.pack(it->second);
130        }
131        return o;
132    }
133};
134
135template <typename K, typename V, typename Hash, typename Pred, typename Alloc>
136struct object_with_zone<MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc> > {
137    void operator()(msgpack::object::with_zone& o, const MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc>& v) const {
138        o.type = msgpack::type::MAP;
139        if(v.empty()) {
140            o.via.map.ptr  = nullptr;
141            o.via.map.size = 0;
142        } else {
143            uint32_t size = checked_get_container_size(v.size());
144            msgpack::object_kv* p = static_cast<msgpack::object_kv*>(o.zone.allocate_align(sizeof(msgpack::object_kv)*size));
145            msgpack::object_kv* const pend = p + size;
146            o.via.map.ptr  = p;
147            o.via.map.size = size;
148            typename MSGPACK_STD_TR1::unordered_multimap<K, V, Hash, Pred, Alloc>::const_iterator it(v.begin());
149            do {
150                p->key = msgpack::object(it->first, o.zone);
151                p->val = msgpack::object(it->second, o.zone);
152                ++p;
153                ++it;
154            } while(p < pend);
155        }
156    }
157};
158
159} // namespace adaptor
160
161/// @cond
162} // MSGPACK_API_VERSION_NAMESPACE(v1)
163/// @endcond
164
165} // namespace msgpack
166
167#undef MSGPACK_STD_TR1
168
169#endif // MSGPACK_STD_TR1
170
171#endif // MSGPACK_TYPE_TR1_UNORDERED_MAP_HPP
172