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