Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(292)

Side by Side Diff: mojo/public/cpp/bindings/map.h

Issue 1683863002: Mojo C++ bindings: make mojo::Map<K,V> more friendly with std::map<K,V>. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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_
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/lib/map_serialization.h ('k') | mojo/public/cpp/bindings/tests/map_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698