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