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 THIRD_PARTY_MOJO_SRC_MOJO_PUBLIC_CPP_BINDINGS_MAP_H_ | |
6 #define THIRD_PARTY_MOJO_SRC_MOJO_PUBLIC_CPP_BINDINGS_MAP_H_ | |
7 | |
8 #include <map> | |
9 | |
10 #include "third_party/mojo/src/mojo/public/cpp/bindings/lib/map_internal.h" | |
11 #include "third_party/mojo/src/mojo/public/cpp/bindings/lib/value_traits.h" | |
12 | |
13 namespace mojo { | |
14 | |
15 // A move-only map that can handle move-only values. Map has the following | |
16 // characteristics: | |
17 // - The map itself can be null, and this is distinct from empty. | |
18 // - Keys must not be move-only. | |
19 // - The Key-type's "<" operator is used to sort the entries, and also is | |
20 // used to determine equality of the key values. | |
21 // - There can only be one entry per unique key. | |
22 // - Values of move-only types will be moved into the Map when they are added | |
23 // using the insert() method. | |
24 template <typename Key, typename Value> | |
25 class Map { | |
26 MOJO_MOVE_ONLY_TYPE(Map) | |
27 | |
28 public: | |
29 // Map keys cannot be move only classes. | |
30 static_assert(!internal::IsMoveOnlyType<Key>::value, | |
31 "Map keys cannot be move only types."); | |
32 | |
33 typedef internal::MapTraits<Key, | |
34 Value, | |
35 internal::IsMoveOnlyType<Value>::value> Traits; | |
36 typedef typename Traits::KeyStorageType KeyStorageType; | |
37 typedef typename Traits::KeyRefType KeyRefType; | |
38 typedef typename Traits::KeyConstRefType KeyConstRefType; | |
39 typedef typename Traits::KeyForwardType KeyForwardType; | |
40 | |
41 typedef typename Traits::ValueStorageType ValueStorageType; | |
42 typedef typename Traits::ValueRefType ValueRefType; | |
43 typedef typename Traits::ValueConstRefType ValueConstRefType; | |
44 typedef typename Traits::ValueForwardType ValueForwardType; | |
45 | |
46 typedef internal::Map_Data<typename internal::WrapperTraits<Key>::DataType, | |
47 typename internal::WrapperTraits<Value>::DataType> | |
48 Data_; | |
49 | |
50 Map() : is_null_(true) {} | |
51 | |
52 // Constructs a non-null Map containing the specified |keys| mapped to the | |
53 // corresponding |values|. | |
54 Map(mojo::Array<Key> keys, mojo::Array<Value> values) : is_null_(false) { | |
55 MOJO_DCHECK(keys.size() == values.size()); | |
56 Traits::InitializeFrom(&map_, keys.Pass(), values.Pass()); | |
57 } | |
58 | |
59 ~Map() { Traits::Finalize(&map_); } | |
60 | |
61 Map(Map&& other) : is_null_(true) { Take(&other); } | |
62 Map& operator=(Map&& other) { | |
63 Take(&other); | |
64 return *this; | |
65 } | |
66 | |
67 // Copies the contents of some other type of map into a new Map using a | |
68 // TypeConverter. A TypeConverter for std::map to Map is defined below. | |
69 template <typename U> | |
70 static Map From(const U& other) { | |
71 return TypeConverter<Map, U>::Convert(other); | |
72 } | |
73 | |
74 // Copies the contents of the Map into some other type of map. A TypeConverter | |
75 // for Map to std::map is defined below. | |
76 template <typename U> | |
77 U To() const { | |
78 return TypeConverter<U, Map>::Convert(*this); | |
79 } | |
80 | |
81 // Destroys the contents of the Map and leaves it in the null state. | |
82 void reset() { | |
83 if (!map_.empty()) { | |
84 Traits::Finalize(&map_); | |
85 map_.clear(); | |
86 } | |
87 is_null_ = true; | |
88 } | |
89 | |
90 bool is_null() const { return is_null_; } | |
91 | |
92 // Indicates the number of keys in the map. | |
93 size_t size() const { return map_.size(); } | |
94 | |
95 void mark_non_null() { is_null_ = false; } | |
96 | |
97 // Inserts a key-value pair into the map, moving the value by calling its | |
98 // Pass() method if it is a move-only type. Like std::map, this does not | |
99 // insert |value| if |key| is already a member of the map. | |
100 void insert(KeyForwardType key, ValueForwardType value) { | |
101 is_null_ = false; | |
102 Traits::Insert(&map_, key, value); | |
103 } | |
104 | |
105 // Returns a reference to the value associated with the specified key, | |
106 // crashing the process if the key is not present in the map. | |
107 ValueRefType at(KeyForwardType key) { return Traits::at(&map_, key); } | |
108 ValueConstRefType at(KeyForwardType key) const { | |
109 return Traits::at(&map_, key); | |
110 } | |
111 | |
112 // Returns a reference to the value associated with the specified key, | |
113 // creating a new entry if the key is not already present in the map. A | |
114 // newly-created value will be value-initialized (meaning that it will be | |
115 // initialized by the default constructor of the value type, if any, or else | |
116 // will be zero-initialized). | |
117 ValueRefType operator[](KeyForwardType key) { | |
118 is_null_ = false; | |
119 return Traits::GetOrInsert(&map_, key); | |
120 } | |
121 | |
122 // Swaps the contents of this Map with another Map of the same type (including | |
123 // nullness). | |
124 void Swap(Map<Key, Value>* other) { | |
125 std::swap(is_null_, other->is_null_); | |
126 map_.swap(other->map_); | |
127 } | |
128 | |
129 // Swaps the contents of this Map with an std::map containing keys and values | |
130 // of the same type. Since std::map cannot represent the null state, the | |
131 // std::map will be empty if Map is null. The Map will always be left in a | |
132 // non-null state. | |
133 void Swap(std::map<Key, Value>* other) { | |
134 is_null_ = false; | |
135 map_.swap(*other); | |
136 } | |
137 | |
138 // Removes all contents from the Map and places them into parallel key/value | |
139 // arrays. Each key will be copied from the source to the destination, and | |
140 // values will be copied unless their type is designated move-only, in which | |
141 // case they will be passed by calling their Pass() method. Either way, the | |
142 // Map will be left in a null state. | |
143 void DecomposeMapTo(mojo::Array<Key>* keys, mojo::Array<Value>* values) { | |
144 Traits::Decompose(&map_, keys, values); | |
145 Traits::Finalize(&map_); | |
146 map_.clear(); | |
147 is_null_ = true; | |
148 } | |
149 | |
150 // Returns a new Map that contains a copy of the contents of this map. If the | |
151 // values are of a type that is designated move-only, they will be cloned | |
152 // using the Clone() method of the type. Please note that calling this method | |
153 // will fail compilation if the value type cannot be cloned (which usually | |
154 // means that it is a Mojo handle type or a type that contains Mojo handles). | |
155 Map Clone() const { | |
156 Map result; | |
157 result.is_null_ = is_null_; | |
158 Traits::Clone(map_, &result.map_); | |
159 return result.Pass(); | |
160 } | |
161 | |
162 // Indicates whether the contents of this map are equal to those of another | |
163 // Map (including nullness). Keys are compared by the != operator. Values are | |
164 // compared as follows: | |
165 // - Map, Array, Struct, or StructPtr values are compared by their Equals() | |
166 // method. | |
167 // - ScopedHandleBase-derived types are compared by their handles. | |
168 // - Values of other types are compared by their "==" operator. | |
169 bool Equals(const Map& other) const { | |
170 if (is_null() != other.is_null()) | |
171 return false; | |
172 if (size() != other.size()) | |
173 return false; | |
174 auto i = begin(); | |
175 auto j = other.begin(); | |
176 while (i != end()) { | |
177 if (i.GetKey() != j.GetKey()) | |
178 return false; | |
179 if (!internal::ValueTraits<Value>::Equals(i.GetValue(), j.GetValue())) | |
180 return false; | |
181 ++i; | |
182 ++j; | |
183 } | |
184 return true; | |
185 } | |
186 | |
187 // A read-only iterator for Map. | |
188 class ConstMapIterator { | |
189 public: | |
190 ConstMapIterator( | |
191 const typename std::map<KeyStorageType, | |
192 ValueStorageType>::const_iterator& it) | |
193 : it_(it) {} | |
194 | |
195 // Returns a const reference to the key and value. | |
196 KeyConstRefType GetKey() { return Traits::GetKey(it_); } | |
197 ValueConstRefType GetValue() { return Traits::GetValue(it_); } | |
198 | |
199 ConstMapIterator& operator*() { | |
200 return *this; | |
201 } | |
202 ConstMapIterator& operator++() { | |
203 it_++; | |
204 return *this; | |
205 } | |
206 bool operator!=(const ConstMapIterator& rhs) const { | |
207 return it_ != rhs.it_; | |
208 } | |
209 bool operator==(const ConstMapIterator& rhs) const { | |
210 return it_ == rhs.it_; | |
211 } | |
212 | |
213 private: | |
214 typename std::map<KeyStorageType, ValueStorageType>::const_iterator it_; | |
215 }; | |
216 | |
217 // Provide read-only iteration over map members in a way similar to STL | |
218 // collections. | |
219 ConstMapIterator begin() const { return ConstMapIterator(map_.begin()); } | |
220 ConstMapIterator end() const { return ConstMapIterator(map_.end()); } | |
221 | |
222 // Returns the iterator pointing to the entry for |key|, if present, or else | |
223 // returns end(). | |
224 ConstMapIterator find(KeyForwardType key) const { | |
225 return ConstMapIterator(map_.find(key)); | |
226 } | |
227 | |
228 private: | |
229 typedef std::map<KeyStorageType, ValueStorageType> Map::*Testable; | |
230 | |
231 public: | |
232 // The Map may be used in boolean expressions to determine if it is non-null, | |
233 // but is not implicitly convertible to an actual bool value (which would be | |
234 // dangerous). | |
235 operator Testable() const { return is_null_ ? 0 : &Map::map_; } | |
236 | |
237 private: | |
238 // Forbid the == and != operators explicitly, otherwise Map will be converted | |
239 // to Testable to do == or != comparison. | |
240 template <typename T, typename U> | |
241 bool operator==(const Map<T, U>& other) const = delete; | |
242 template <typename T, typename U> | |
243 bool operator!=(const Map<T, U>& other) const = delete; | |
244 | |
245 void Take(Map* other) { | |
246 reset(); | |
247 Swap(other); | |
248 } | |
249 | |
250 std::map<KeyStorageType, ValueStorageType> map_; | |
251 bool is_null_; | |
252 }; | |
253 | |
254 // Copies the contents of an std::map to a new Map, optionally changing the | |
255 // types of the keys and values along the way using TypeConverter. | |
256 template <typename MojoKey, | |
257 typename MojoValue, | |
258 typename STLKey, | |
259 typename STLValue> | |
260 struct TypeConverter<Map<MojoKey, MojoValue>, std::map<STLKey, STLValue>> { | |
261 static Map<MojoKey, MojoValue> Convert( | |
262 const std::map<STLKey, STLValue>& input) { | |
263 Map<MojoKey, MojoValue> result; | |
264 result.mark_non_null(); | |
265 for (auto& pair : input) { | |
266 result.insert(TypeConverter<MojoKey, STLKey>::Convert(pair.first), | |
267 TypeConverter<MojoValue, STLValue>::Convert(pair.second)); | |
268 } | |
269 return result.Pass(); | |
270 } | |
271 }; | |
272 | |
273 // Copies the contents of a Map to an std::map, optionally changing the types of | |
274 // the keys and values along the way using TypeConverter. | |
275 template <typename MojoKey, | |
276 typename MojoValue, | |
277 typename STLKey, | |
278 typename STLValue> | |
279 struct TypeConverter<std::map<STLKey, STLValue>, Map<MojoKey, MojoValue>> { | |
280 static std::map<STLKey, STLValue> Convert( | |
281 const Map<MojoKey, MojoValue>& input) { | |
282 std::map<STLKey, STLValue> result; | |
283 if (!input.is_null()) { | |
284 for (auto it = input.begin(); it != input.end(); ++it) { | |
285 result.insert(std::make_pair( | |
286 TypeConverter<STLKey, MojoKey>::Convert(it.GetKey()), | |
287 TypeConverter<STLValue, MojoValue>::Convert(it.GetValue()))); | |
288 } | |
289 } | |
290 return result; | |
291 } | |
292 }; | |
293 | |
294 } // namespace mojo | |
295 | |
296 #endif // THIRD_PARTY_MOJO_SRC_MOJO_PUBLIC_CPP_BINDINGS_MAP_H_ | |
OLD | NEW |