| 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 |