OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ | |
7 | |
8 #include <map> | |
9 | |
10 #include "mojo/public/cpp/bindings/array.h" | |
11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" | |
12 | |
13 namespace mojo { | |
14 namespace internal { | |
15 | |
16 template <typename Key, typename Value, bool kValueIsMoveOnlyType> | |
17 struct MapTraits {}; | |
18 | |
19 template <typename Key, typename Value> | |
20 struct MapTraits<Key, Value, false> { | |
21 // Map keys can't be move only types. | |
22 static_assert(!internal::IsMoveOnlyType<Key>::value, | |
23 "Map keys can not be move only types."); | |
24 | |
25 typedef Key KeyStorageType; | |
26 typedef Key& KeyRefType; | |
27 typedef const Key& KeyConstRefType; | |
28 typedef KeyConstRefType KeyForwardType; | |
29 | |
30 typedef Value ValueStorageType; | |
31 typedef Value& ValueRefType; | |
32 typedef const Value& ValueConstRefType; | |
33 typedef ValueConstRefType ValueForwardType; | |
34 | |
35 static inline void InitializeFrom( | |
36 std::map<KeyStorageType, ValueStorageType>* m, | |
37 mojo::Array<Key> keys, | |
38 mojo::Array<Value> values) { | |
39 for (size_t i = 0; i < keys.size(); ++i) | |
40 Insert(m, keys[i], values[i]); | |
41 } | |
42 static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m, | |
43 mojo::Array<Key>* keys, | |
44 mojo::Array<Value>* values) { | |
45 keys->resize(m->size()); | |
46 values->resize(m->size()); | |
47 int i = 0; | |
48 for (typename std::map<KeyStorageType, ValueStorageType>::iterator | |
49 it = m->begin(); | |
50 it != m->end(); | |
51 ++it, ++i) { | |
52 (*keys)[i] = it->first; | |
53 (*values)[i] = it->second; | |
54 } | |
55 } | |
56 static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) {} | |
57 static inline ValueRefType at(std::map<KeyStorageType, ValueStorageType>* m, | |
58 KeyForwardType key) { | |
59 // We don't have C++11 library support yet, so we have to emulate the crash | |
60 // on a non-existant key. | |
61 auto it = m->find(key); | |
62 MOJO_CHECK(it != m->end()); | |
63 return it->second; | |
64 } | |
65 static inline ValueConstRefType at( | |
66 const std::map<KeyStorageType, ValueStorageType>* m, | |
67 KeyForwardType key) { | |
68 // We don't have C++11 library support yet, so we have to emulate the crash | |
69 // on a non-existant key. | |
70 auto it = m->find(key); | |
71 MOJO_CHECK(it != m->end()); | |
72 return it->second; | |
73 } | |
74 static inline void Insert(std::map<KeyStorageType, ValueStorageType>* m, | |
75 KeyForwardType key, | |
76 ValueForwardType value) { | |
77 m->insert(std::make_pair(key, value)); | |
78 } | |
79 static inline KeyConstRefType GetKey( | |
80 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
81 it) { | |
82 return it->first; | |
83 } | |
84 static inline ValueConstRefType GetValue( | |
85 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
86 it) { | |
87 return it->second; | |
88 } | |
89 static inline ValueRefType GetValue( | |
90 const typename std::map<KeyStorageType, ValueStorageType>::iterator& it) { | |
91 return it->second; | |
92 } | |
93 static inline void Clone( | |
94 const std::map<KeyStorageType, ValueStorageType>& src, | |
95 std::map<KeyStorageType, ValueStorageType>* dst) { | |
96 dst->clear(); | |
97 for (auto it = src.begin(); it != src.end(); ++it) | |
98 dst->insert(*it); | |
99 } | |
100 }; | |
101 | |
102 template <typename Key, typename Value> | |
103 struct MapTraits<Key, Value, true> { | |
104 // Map keys can't be move only types. | |
105 static_assert(!internal::IsMoveOnlyType<Key>::value, | |
106 "Map keys can not be move only types."); | |
107 | |
108 typedef Key KeyStorageType; | |
109 typedef Key& KeyRefType; | |
110 typedef const Key& KeyConstRefType; | |
111 typedef KeyConstRefType KeyForwardType; | |
112 | |
113 struct ValueStorageType { | |
114 // Make 8-byte aligned. | |
115 char buf[sizeof(Value) + (8 - (sizeof(Value) % 8)) % 8]; | |
116 }; | |
117 typedef Value& ValueRefType; | |
118 typedef const Value& ValueConstRefType; | |
119 typedef Value ValueForwardType; | |
120 | |
121 static inline void InitializeFrom( | |
122 std::map<KeyStorageType, ValueStorageType>* m, | |
123 mojo::Array<Key> keys, | |
124 mojo::Array<Value> values) { | |
125 for (size_t i = 0; i < keys.size(); ++i) { | |
126 // We can't call Insert() directly because of forwarding. Emulate the | |
yzshen1
2014/10/09 17:41:58
(just out of curiosity) what is the forwarding iss
Elliot Glaysher
2014/10/09 19:15:19
Experimented more; calling Insert() directly works
| |
127 // logic there to ensure that we handle invalid maps with duplicate keys. | |
128 auto it = m->find(keys[i]); | |
129 if (it == m->end()) | |
130 new ((*m)[keys[i]].buf) Value(values[i].Pass()); | |
131 } | |
132 } | |
133 static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m, | |
134 mojo::Array<Key>* keys, | |
135 mojo::Array<Value>* values) { | |
136 keys->resize(m->size()); | |
137 values->resize(m->size()); | |
138 int i = 0; | |
139 for (typename std::map<KeyStorageType, ValueStorageType>::iterator | |
140 it = m->begin(); | |
141 it != m->end(); | |
142 ++it, ++i) { | |
143 (*keys)[i] = it->first; | |
144 (*values)[i] = GetValue(it).Pass(); | |
145 } | |
146 } | |
147 static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) { | |
148 for (auto& pair : *m) | |
149 reinterpret_cast<Value*>(pair.second.buf)->~Value(); | |
150 } | |
151 static inline ValueRefType at(std::map<KeyStorageType, ValueStorageType>* m, | |
152 KeyForwardType key) { | |
153 // We don't have C++11 library support yet, so we have to emulate the crash | |
154 // on a non-existant key. | |
155 auto it = m->find(key); | |
156 MOJO_CHECK(it != m->end()); | |
157 return GetValue(it); | |
158 } | |
159 static inline ValueConstRefType at( | |
160 const std::map<KeyStorageType, ValueStorageType>* m, | |
161 KeyForwardType key) { | |
162 // We don't have C++11 library support yet, so we have to emulate the crash | |
163 // on a non-existant key. | |
164 auto it = m->find(key); | |
165 MOJO_CHECK(it != m->end()); | |
166 return GetValue(it); | |
167 } | |
168 static inline void Insert(std::map<KeyStorageType, ValueStorageType>* m, | |
169 KeyForwardType key, | |
170 ValueRefType value) { | |
171 // STL insert() doesn't insert |value| if |key| is already part of |m|. We | |
172 // have to use operator[] to initialize into the storage buffer, but we | |
173 // have to do a manual check so that we don't overwrite an existing object. | |
174 auto it = m->find(key); | |
175 if (it == m->end()) | |
176 new ((*m)[key].buf) Value(value.Pass()); | |
177 } | |
178 static inline KeyConstRefType GetKey( | |
179 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
180 it) { | |
181 return it->first; | |
182 } | |
183 static inline ValueConstRefType GetValue( | |
184 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
185 it) { | |
186 return *reinterpret_cast<const Value*>(it->second.buf); | |
187 } | |
188 static inline ValueRefType GetValue( | |
189 const typename std::map<KeyStorageType, ValueStorageType>::iterator& it) { | |
190 return *reinterpret_cast<Value*>(it->second.buf); | |
191 } | |
192 static inline void Clone( | |
193 const std::map<KeyStorageType, ValueStorageType>& src, | |
194 std::map<KeyStorageType, ValueStorageType>* dst) { | |
195 Finalize(dst); | |
196 dst->clear(); | |
197 for (auto it = src.begin(); it != src.end(); ++it) | |
198 new ((*dst)[it->first].buf) Value(GetValue(it).Clone()); | |
199 } | |
200 }; | |
201 | |
202 } // namespace internal | |
203 } // namespace mojo | |
204 | |
205 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ | |
OLD | NEW |