Chromium Code Reviews| 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 |