OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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_WTF_MAP_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_WTF_MAP_H_ | |
7 | |
8 #include <stddef.h> | |
9 #include <utility> | |
10 | |
11 #include "base/move.h" | |
12 #include "mojo/public/cpp/bindings/lib/template_util.h" | |
13 #include "mojo/public/cpp/bindings/type_converter.h" | |
14 #include "third_party/WebKit/Source/wtf/HashMap.h" | |
15 #include "third_party/WebKit/Source/wtf/text/StringHash.h" | |
16 | |
17 namespace mojo { | |
18 | |
19 // Represents a map backed by WTF::HashMap. Comparing with WTF::HashMap, | |
20 // mojo::WTFMap is move-only and can be null. | |
21 // | |
22 // It is easy to convert between WTF::HashMap<K, V> and mojo::WTFMap<K, V>: | |
23 // - constructor WTFMap(WTF::HashMap<K, V>&&) takes the contents of a | |
24 // WTF::HashMap<K, V>; | |
25 // - method PassStorage() passes the underlying WTF::HashMap. | |
26 template <typename Key, typename Value> | |
27 class WTFMap { | |
28 MOVE_ONLY_TYPE_FOR_CPP_03(WTFMap); | |
29 | |
30 public: | |
31 using Iterator = typename WTF::HashMap<Key, Value>::iterator; | |
32 using ConstIterator = typename WTF::HashMap<Key, Value>::const_iterator; | |
33 | |
34 // Constructs an empty map. | |
35 WTFMap() : is_null_(false) {} | |
36 // Constructs a null map. | |
37 WTFMap(std::nullptr_t null_pointer) : is_null_(true) {} | |
38 | |
39 ~WTFMap() {} | |
40 | |
41 WTFMap(WTF::HashMap<Key, Value>&& other) | |
42 : map_(std::move(other)), is_null_(false) {} | |
43 WTFMap(WTFMap&& other) : is_null_(true) { Take(&other); } | |
44 | |
45 WTFMap& operator=(WTF::HashMap<Key, Value>&& other) { | |
46 is_null_ = false; | |
47 map_ = std::move(other); | |
48 return *this; | |
49 } | |
50 WTFMap& operator=(WTFMap&& other) { | |
51 Take(&other); | |
52 return *this; | |
53 } | |
54 | |
55 WTFMap& operator=(std::nullptr_t null_pointer) { | |
56 is_null_ = true; | |
57 map_.clear(); | |
58 return *this; | |
59 } | |
60 | |
61 // Copies the contents of some other type of map into a new WTFMap using a | |
62 // TypeConverter. | |
63 template <typename U> | |
64 static WTFMap From(const U& other) { | |
65 return TypeConverter<WTFMap, U>::Convert(other); | |
66 } | |
67 | |
68 // Copies the contents of the WTFMap into some other type of map. | |
69 template <typename U> | |
70 U To() const { | |
71 return TypeConverter<U, WTFMap>::Convert(*this); | |
72 } | |
73 | |
74 // Indicates whether the map is null (which is distinct from empty). | |
75 bool is_null() const { return is_null_; } | |
76 | |
77 // Indicates whether the map is empty (which is distinct from null). | |
78 bool empty() const { return map_.isEmpty() && !is_null_; } | |
79 | |
80 // Indicates the number of keys in the map, which will be zero if the map is | |
81 // null. | |
82 size_t size() const { return map_.size(); } | |
83 | |
84 // Inserts a key-value pair into the map. Like WTF::HashMap::add(), this does | |
85 // not insert |value| if |key| is already a member of the map. | |
86 void insert(const Key& key, const Value& value) { | |
87 is_null_ = false; | |
88 map_.add(key, value); | |
89 } | |
90 void insert(const Key& key, Value&& value) { | |
91 is_null_ = false; | |
92 map_.add(key, std::move(value)); | |
93 } | |
94 | |
95 // Returns a reference to the value associated with the specified key, | |
96 // crashing the process if the key is not present in the map. | |
97 Value& at(const Key& key) { return map_.find(key)->value; } | |
98 const Value& at(const Key& key) const { return map_.find(key)->value; } | |
99 | |
100 // Returns a reference to the value associated with the specified key, | |
101 // creating a new entry if the key is not already present in the map. A | |
102 // newly-created value will be value-initialized (meaning that it will be | |
103 // initialized by the default constructor of the value type, if any, or else | |
104 // will be zero-initialized). | |
105 Value& operator[](const Key& key) { | |
106 is_null_ = false; | |
107 if (!map_.contains(key)) | |
108 map_.add(key, Value()); | |
109 return at(key); | |
110 } | |
111 | |
112 // Sets the map to empty (even if previously it was null). | |
113 void SetToEmpty() { | |
114 is_null_ = false; | |
115 map_.clear(); | |
116 } | |
117 | |
118 // Returns a const reference to the WTF::HashMap managed by this class. If | |
119 // this object is null, the return value will be an empty map. | |
120 const WTF::HashMap<Key, Value>& storage() const { return map_; } | |
121 | |
122 // Passes the underlying storage and resets this map to null. | |
123 WTF::HashMap<Key, Value> PassStorage() { | |
124 is_null_ = true; | |
125 return std::move(map_); | |
126 } | |
127 | |
128 // Swaps the contents of this WTFMap with another WTFMap of the same type | |
129 // (including nullness). | |
130 void Swap(WTFMap<Key, Value>* other) { | |
131 std::swap(is_null_, other->is_null_); | |
132 map_.swap(other->map_); | |
133 } | |
134 | |
135 // Swaps the contents of this WTFMap with an WTF::HashMap containing keys and | |
136 // values of the same type. Since WTF::HashMap cannot represent the null | |
137 // state, the WTF::HashMap will be empty if WTFMap is null. The WTFMap will | |
138 // always be left in a non-null state. | |
139 void Swap(WTF::HashMap<Key, Value>* other) { | |
140 is_null_ = false; | |
141 map_.swap(*other); | |
142 } | |
143 | |
144 // Returns a new WTFMap that contains a copy of the contents of this map. If | |
145 // the key/value type defines a Clone() method, it will be used; otherwise | |
146 // copy constructor/assignment will be used. | |
147 // | |
148 // Please note that calling this method will fail compilation if the key/value | |
149 // type cannot be cloned (which usually means that it is a Mojo handle type or | |
150 // a type containing Mojo handles). | |
151 WTFMap Clone() const { | |
152 WTFMap result; | |
153 result.is_null_ = is_null_; | |
154 auto map_end = map_.end(); | |
155 for (auto it = map_.begin(); it != map_end; ++it) | |
156 result.map_.add(internal::Clone(it->key), internal::Clone(it->value)); | |
157 return result; | |
158 } | |
159 | |
160 // Indicates whether the contents of this map are equal to those of another | |
161 // WTFMap (including nullness). If the key/value type defines an Equals() | |
162 // method, it will be used; otherwise == operator will be used. | |
163 bool Equals(const WTFMap& other) const { | |
164 if (is_null() != other.is_null()) | |
165 return false; | |
166 if (size() != other.size()) | |
167 return false; | |
168 | |
169 auto this_end = map_.end(); | |
170 auto other_end = other.map_.end(); | |
171 | |
172 for (auto iter = map_.begin(); iter != this_end; ++iter) { | |
173 auto other_iter = other.map_.find(iter->key); | |
174 if (other_iter == other_end || | |
175 !internal::Equals(iter->value, other_iter->value)) { | |
176 return false; | |
177 } | |
178 } | |
179 return true; | |
180 } | |
181 | |
182 ConstIterator begin() const { return map_.begin(); } | |
183 Iterator begin() { return map_.begin(); } | |
184 | |
185 ConstIterator end() const { return map_.end(); } | |
186 Iterator end() { return map_.end(); } | |
187 | |
188 // Returns the iterator pointing to the entry for |key|, if present, or else | |
189 // returns end(). | |
190 ConstIterator find(const Key& key) const { return map_.find(key); } | |
191 Iterator find(const Key& key) { return map_.find(key); } | |
192 | |
193 private: | |
194 typedef WTF::HashMap<Key, Value> WTFMap::*Testable; | |
195 | |
196 public: | |
197 // The WTFMap may be used in boolean expressions to determine if it is | |
198 // non-null, but is not implicitly convertible to an actual bool value (which | |
199 // would be dangerous). | |
200 operator Testable() const { return is_null_ ? 0 : &WTFMap::map_; } | |
Yuta Kitamura
2016/06/06 05:29:42
Now you can safely use "explicit operator bool()".
yzshen1
2016/06/07 23:49:11
Done. Good point!
| |
201 | |
202 private: | |
203 // Forbid the == and != operators explicitly, otherwise WTFMap will be | |
204 // converted to Testable to do == or != comparison. | |
205 template <typename T, typename U> | |
206 bool operator==(const WTFMap<T, U>& other) const = delete; | |
207 template <typename T, typename U> | |
208 bool operator!=(const WTFMap<T, U>& other) const = delete; | |
209 | |
210 void Take(WTFMap* other) { | |
211 operator=(nullptr); | |
212 Swap(other); | |
213 } | |
214 | |
215 WTF::HashMap<Key, Value> map_; | |
Yuta Kitamura
2016/06/06 05:29:42
What's a bit tricky is that WTF::HashMap does not
yzshen1
2016/06/07 23:49:11
I have added comments. And also added code to reje
| |
216 bool is_null_; | |
217 }; | |
218 | |
219 } // namespace mojo | |
220 | |
221 #endif // MOJO_PUBLIC_CPP_BINDINGS_WTF_MAP_H_ | |
OLD | NEW |