| OLD | NEW |
| 1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 * | 3 // found in the LICENSE file. |
| 4 * This library is free software; you can redistribute it and/or | |
| 5 * modify it under the terms of the GNU Library General Public | |
| 6 * License as published by the Free Software Foundation; either | |
| 7 * version 2 of the License, or (at your option) any later version. | |
| 8 * | |
| 9 * This library is distributed in the hope that it will be useful, | |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 * Library General Public License for more details. | |
| 13 * | |
| 14 * You should have received a copy of the GNU Library General Public License | |
| 15 * along with this library; see the file COPYING.LIB. If not, write to | |
| 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
| 17 * Boston, MA 02110-1301, USA. | |
| 18 * | |
| 19 */ | |
| 20 | 4 |
| 21 #ifndef WTF_HashMap_h | 5 #include "platform/wtf/HashMap.h" |
| 22 #define WTF_HashMap_h | |
| 23 | 6 |
| 24 #include "wtf/HashTable.h" | 7 // The contents of this header was moved to platform/wtf as part of |
| 25 #include "wtf/allocator/PartitionAllocator.h" | 8 // WTF migration project. See the following post for details: |
| 26 #include <initializer_list> | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
| 27 | |
| 28 namespace WTF { | |
| 29 | |
| 30 template <typename KeyTraits, typename MappedTraits> | |
| 31 struct HashMapValueTraits; | |
| 32 | |
| 33 struct KeyValuePairKeyExtractor { | |
| 34 STATIC_ONLY(KeyValuePairKeyExtractor); | |
| 35 template <typename T> | |
| 36 static const typename T::KeyType& extract(const T& p) { | |
| 37 return p.key; | |
| 38 } | |
| 39 }; | |
| 40 | |
| 41 // Note: empty or deleted key values are not allowed, using them may lead to | |
| 42 // undefined behavior. For pointer keys this means that null pointers are not | |
| 43 // allowed unless you supply custom key traits. | |
| 44 template <typename KeyArg, | |
| 45 typename MappedArg, | |
| 46 typename HashArg = typename DefaultHash<KeyArg>::Hash, | |
| 47 typename KeyTraitsArg = HashTraits<KeyArg>, | |
| 48 typename MappedTraitsArg = HashTraits<MappedArg>, | |
| 49 typename Allocator = PartitionAllocator> | |
| 50 class HashMap { | |
| 51 USE_ALLOCATOR(HashMap, Allocator); | |
| 52 | |
| 53 private: | |
| 54 typedef KeyTraitsArg KeyTraits; | |
| 55 typedef MappedTraitsArg MappedTraits; | |
| 56 typedef HashMapValueTraits<KeyTraits, MappedTraits> ValueTraits; | |
| 57 | |
| 58 public: | |
| 59 typedef typename KeyTraits::TraitType KeyType; | |
| 60 typedef const typename KeyTraits::PeekInType& KeyPeekInType; | |
| 61 typedef typename MappedTraits::TraitType MappedType; | |
| 62 typedef typename ValueTraits::TraitType ValueType; | |
| 63 using value_type = ValueType; | |
| 64 | |
| 65 private: | |
| 66 typedef typename MappedTraits::PeekOutType MappedPeekType; | |
| 67 | |
| 68 typedef HashArg HashFunctions; | |
| 69 | |
| 70 typedef HashTable<KeyType, | |
| 71 ValueType, | |
| 72 KeyValuePairKeyExtractor, | |
| 73 HashFunctions, | |
| 74 ValueTraits, | |
| 75 KeyTraits, | |
| 76 Allocator> | |
| 77 HashTableType; | |
| 78 | |
| 79 class HashMapKeysProxy; | |
| 80 class HashMapValuesProxy; | |
| 81 | |
| 82 public: | |
| 83 HashMap() { | |
| 84 static_assert(Allocator::isGarbageCollected || | |
| 85 !IsPointerToGarbageCollectedType<KeyArg>::value, | |
| 86 "Cannot put raw pointers to garbage-collected classes into " | |
| 87 "an off-heap HashMap. Use HeapHashMap<> instead."); | |
| 88 static_assert(Allocator::isGarbageCollected || | |
| 89 !IsPointerToGarbageCollectedType<MappedArg>::value, | |
| 90 "Cannot put raw pointers to garbage-collected classes into " | |
| 91 "an off-heap HashMap. Use HeapHashMap<> instead."); | |
| 92 } | |
| 93 HashMap(const HashMap&) = default; | |
| 94 HashMap& operator=(const HashMap&) = default; | |
| 95 HashMap(HashMap&&) = default; | |
| 96 HashMap& operator=(HashMap&&) = default; | |
| 97 | |
| 98 // For example, HashMap<int, int>({{1, 11}, {2, 22}, {3, 33}}) will give you | |
| 99 // a HashMap containing a mapping {1 -> 11, 2 -> 22, 3 -> 33}. | |
| 100 HashMap(std::initializer_list<ValueType> elements); | |
| 101 HashMap& operator=(std::initializer_list<ValueType> elements); | |
| 102 | |
| 103 typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator; | |
| 104 typedef HashTableConstIteratorAdapter<HashTableType, ValueType> | |
| 105 const_iterator; | |
| 106 typedef typename HashTableType::AddResult AddResult; | |
| 107 | |
| 108 void swap(HashMap& ref) { m_impl.swap(ref.m_impl); } | |
| 109 | |
| 110 unsigned size() const; | |
| 111 unsigned capacity() const; | |
| 112 void reserveCapacityForSize(unsigned size) { | |
| 113 m_impl.reserveCapacityForSize(size); | |
| 114 } | |
| 115 | |
| 116 bool isEmpty() const; | |
| 117 | |
| 118 // iterators iterate over pairs of keys and values | |
| 119 iterator begin(); | |
| 120 iterator end(); | |
| 121 const_iterator begin() const; | |
| 122 const_iterator end() const; | |
| 123 | |
| 124 HashMapKeysProxy& keys() { return static_cast<HashMapKeysProxy&>(*this); } | |
| 125 const HashMapKeysProxy& keys() const { | |
| 126 return static_cast<const HashMapKeysProxy&>(*this); | |
| 127 } | |
| 128 | |
| 129 HashMapValuesProxy& values() { | |
| 130 return static_cast<HashMapValuesProxy&>(*this); | |
| 131 } | |
| 132 const HashMapValuesProxy& values() const { | |
| 133 return static_cast<const HashMapValuesProxy&>(*this); | |
| 134 } | |
| 135 | |
| 136 iterator find(KeyPeekInType); | |
| 137 const_iterator find(KeyPeekInType) const; | |
| 138 bool contains(KeyPeekInType) const; | |
| 139 MappedPeekType at(KeyPeekInType) const; | |
| 140 | |
| 141 // replaces value but not key if key is already present return value is a | |
| 142 // pair of the iterator to the key location, and a boolean that's true if a | |
| 143 // new value was actually added | |
| 144 template <typename IncomingKeyType, typename IncomingMappedType> | |
| 145 AddResult set(IncomingKeyType&&, IncomingMappedType&&); | |
| 146 | |
| 147 // does nothing if key is already present return value is a pair of the | |
| 148 // iterator to the key location, and a boolean that's true if a new value | |
| 149 // was actually added | |
| 150 template <typename IncomingKeyType, typename IncomingMappedType> | |
| 151 AddResult insert(IncomingKeyType&&, IncomingMappedType&&); | |
| 152 | |
| 153 void erase(KeyPeekInType); | |
| 154 void erase(iterator); | |
| 155 void clear(); | |
| 156 template <typename Collection> | |
| 157 void removeAll(const Collection& toBeRemoved) { | |
| 158 WTF::removeAll(*this, toBeRemoved); | |
| 159 } | |
| 160 | |
| 161 MappedType take(KeyPeekInType); // efficient combination of get with remove | |
| 162 | |
| 163 // An alternate version of find() that finds the object by hashing and | |
| 164 // comparing with some other type, to avoid the cost of type | |
| 165 // conversion. HashTranslator must have the following function members: | |
| 166 // static unsigned hash(const T&); | |
| 167 // static bool equal(const ValueType&, const T&); | |
| 168 template <typename HashTranslator, typename T> | |
| 169 iterator find(const T&); | |
| 170 template <typename HashTranslator, typename T> | |
| 171 const_iterator find(const T&) const; | |
| 172 template <typename HashTranslator, typename T> | |
| 173 bool contains(const T&) const; | |
| 174 | |
| 175 // An alternate version of insert() that finds the object by hashing and | |
| 176 // comparing with some other type, to avoid the cost of type conversion if | |
| 177 // the object is already in the table. HashTranslator must have the | |
| 178 // following function members: | |
| 179 // static unsigned hash(const T&); | |
| 180 // static bool equal(const ValueType&, const T&); | |
| 181 // static translate(ValueType&, const T&, unsigned hashCode); | |
| 182 template <typename HashTranslator, | |
| 183 typename IncomingKeyType, | |
| 184 typename IncomingMappedType> | |
| 185 AddResult insert(IncomingKeyType&&, IncomingMappedType&&); | |
| 186 | |
| 187 static bool isValidKey(KeyPeekInType); | |
| 188 | |
| 189 template <typename VisitorDispatcher> | |
| 190 void trace(VisitorDispatcher visitor) { | |
| 191 m_impl.trace(visitor); | |
| 192 } | |
| 193 | |
| 194 private: | |
| 195 template <typename IncomingKeyType, typename IncomingMappedType> | |
| 196 AddResult inlineAdd(IncomingKeyType&&, IncomingMappedType&&); | |
| 197 | |
| 198 HashTableType m_impl; | |
| 199 }; | |
| 200 | |
| 201 template <typename KeyArg, | |
| 202 typename MappedArg, | |
| 203 typename HashArg, | |
| 204 typename KeyTraitsArg, | |
| 205 typename MappedTraitsArg, | |
| 206 typename Allocator> | |
| 207 class HashMap<KeyArg, | |
| 208 MappedArg, | |
| 209 HashArg, | |
| 210 KeyTraitsArg, | |
| 211 MappedTraitsArg, | |
| 212 Allocator>::HashMapKeysProxy : private HashMap<KeyArg, | |
| 213 MappedArg, | |
| 214 HashArg, | |
| 215 KeyTraitsArg, | |
| 216 MappedTraitsArg, | |
| 217 Allocator> { | |
| 218 DISALLOW_NEW(); | |
| 219 | |
| 220 public: | |
| 221 typedef HashMap<KeyArg, | |
| 222 MappedArg, | |
| 223 HashArg, | |
| 224 KeyTraitsArg, | |
| 225 MappedTraitsArg, | |
| 226 Allocator> | |
| 227 HashMapType; | |
| 228 typedef typename HashMapType::iterator::KeysIterator iterator; | |
| 229 typedef typename HashMapType::const_iterator::KeysIterator const_iterator; | |
| 230 | |
| 231 iterator begin() { return HashMapType::begin().keys(); } | |
| 232 | |
| 233 iterator end() { return HashMapType::end().keys(); } | |
| 234 | |
| 235 const_iterator begin() const { return HashMapType::begin().keys(); } | |
| 236 | |
| 237 const_iterator end() const { return HashMapType::end().keys(); } | |
| 238 | |
| 239 private: | |
| 240 friend class HashMap; | |
| 241 | |
| 242 // These are intentionally not implemented. | |
| 243 HashMapKeysProxy(); | |
| 244 HashMapKeysProxy(const HashMapKeysProxy&); | |
| 245 HashMapKeysProxy& operator=(const HashMapKeysProxy&); | |
| 246 ~HashMapKeysProxy(); | |
| 247 }; | |
| 248 | |
| 249 template <typename KeyArg, | |
| 250 typename MappedArg, | |
| 251 typename HashArg, | |
| 252 typename KeyTraitsArg, | |
| 253 typename MappedTraitsArg, | |
| 254 typename Allocator> | |
| 255 class HashMap<KeyArg, | |
| 256 MappedArg, | |
| 257 HashArg, | |
| 258 KeyTraitsArg, | |
| 259 MappedTraitsArg, | |
| 260 Allocator>::HashMapValuesProxy : private HashMap<KeyArg, | |
| 261 MappedArg, | |
| 262 HashArg, | |
| 263 KeyTraitsArg, | |
| 264 MappedTraitsArg, | |
| 265 Allocator> { | |
| 266 DISALLOW_NEW(); | |
| 267 | |
| 268 public: | |
| 269 typedef HashMap<KeyArg, | |
| 270 MappedArg, | |
| 271 HashArg, | |
| 272 KeyTraitsArg, | |
| 273 MappedTraitsArg, | |
| 274 Allocator> | |
| 275 HashMapType; | |
| 276 typedef typename HashMapType::iterator::ValuesIterator iterator; | |
| 277 typedef typename HashMapType::const_iterator::ValuesIterator const_iterator; | |
| 278 | |
| 279 iterator begin() { return HashMapType::begin().values(); } | |
| 280 | |
| 281 iterator end() { return HashMapType::end().values(); } | |
| 282 | |
| 283 const_iterator begin() const { return HashMapType::begin().values(); } | |
| 284 | |
| 285 const_iterator end() const { return HashMapType::end().values(); } | |
| 286 | |
| 287 private: | |
| 288 friend class HashMap; | |
| 289 | |
| 290 // These are intentionally not implemented. | |
| 291 HashMapValuesProxy(); | |
| 292 HashMapValuesProxy(const HashMapValuesProxy&); | |
| 293 HashMapValuesProxy& operator=(const HashMapValuesProxy&); | |
| 294 ~HashMapValuesProxy(); | |
| 295 }; | |
| 296 | |
| 297 template <typename KeyTraits, typename MappedTraits> | |
| 298 struct HashMapValueTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> { | |
| 299 STATIC_ONLY(HashMapValueTraits); | |
| 300 static const bool hasIsEmptyValueFunction = true; | |
| 301 static bool isEmptyValue( | |
| 302 const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& | |
| 303 value) { | |
| 304 return isHashTraitsEmptyValue<KeyTraits>(value.key); | |
| 305 } | |
| 306 }; | |
| 307 | |
| 308 template <typename ValueTraits, typename HashFunctions> | |
| 309 struct HashMapTranslator { | |
| 310 STATIC_ONLY(HashMapTranslator); | |
| 311 template <typename T> | |
| 312 static unsigned hash(const T& key) { | |
| 313 return HashFunctions::hash(key); | |
| 314 } | |
| 315 template <typename T, typename U> | |
| 316 static bool equal(const T& a, const U& b) { | |
| 317 return HashFunctions::equal(a, b); | |
| 318 } | |
| 319 template <typename T, typename U, typename V> | |
| 320 static void translate(T& location, U&& key, V&& mapped) { | |
| 321 location.key = std::forward<U>(key); | |
| 322 ValueTraits::ValueTraits::store(std::forward<V>(mapped), location.value); | |
| 323 } | |
| 324 }; | |
| 325 | |
| 326 template <typename ValueTraits, typename Translator> | |
| 327 struct HashMapTranslatorAdapter { | |
| 328 STATIC_ONLY(HashMapTranslatorAdapter); | |
| 329 template <typename T> | |
| 330 static unsigned hash(const T& key) { | |
| 331 return Translator::hash(key); | |
| 332 } | |
| 333 template <typename T, typename U> | |
| 334 static bool equal(const T& a, const U& b) { | |
| 335 return Translator::equal(a, b); | |
| 336 } | |
| 337 template <typename T, typename U, typename V> | |
| 338 static void translate(T& location, U&& key, V&& mapped, unsigned hashCode) { | |
| 339 Translator::translate(location.key, std::forward<U>(key), hashCode); | |
| 340 ValueTraits::ValueTraits::store(std::forward<V>(mapped), location.value); | |
| 341 } | |
| 342 }; | |
| 343 | |
| 344 template <typename T, | |
| 345 typename U, | |
| 346 typename V, | |
| 347 typename W, | |
| 348 typename X, | |
| 349 typename Y> | |
| 350 HashMap<T, U, V, W, X, Y>::HashMap(std::initializer_list<ValueType> elements) { | |
| 351 if (elements.size()) | |
| 352 m_impl.reserveCapacityForSize(elements.size()); | |
| 353 for (const ValueType& element : elements) | |
| 354 insert(element.key, element.value); | |
| 355 } | |
| 356 | |
| 357 template <typename T, | |
| 358 typename U, | |
| 359 typename V, | |
| 360 typename W, | |
| 361 typename X, | |
| 362 typename Y> | |
| 363 auto HashMap<T, U, V, W, X, Y>::operator=( | |
| 364 std::initializer_list<ValueType> elements) -> HashMap& { | |
| 365 *this = HashMap(std::move(elements)); | |
| 366 return *this; | |
| 367 } | |
| 368 | |
| 369 template <typename T, | |
| 370 typename U, | |
| 371 typename V, | |
| 372 typename W, | |
| 373 typename X, | |
| 374 typename Y> | |
| 375 inline unsigned HashMap<T, U, V, W, X, Y>::size() const { | |
| 376 return m_impl.size(); | |
| 377 } | |
| 378 | |
| 379 template <typename T, | |
| 380 typename U, | |
| 381 typename V, | |
| 382 typename W, | |
| 383 typename X, | |
| 384 typename Y> | |
| 385 inline unsigned HashMap<T, U, V, W, X, Y>::capacity() const { | |
| 386 return m_impl.capacity(); | |
| 387 } | |
| 388 | |
| 389 template <typename T, | |
| 390 typename U, | |
| 391 typename V, | |
| 392 typename W, | |
| 393 typename X, | |
| 394 typename Y> | |
| 395 inline bool HashMap<T, U, V, W, X, Y>::isEmpty() const { | |
| 396 return m_impl.isEmpty(); | |
| 397 } | |
| 398 | |
| 399 template <typename T, | |
| 400 typename U, | |
| 401 typename V, | |
| 402 typename W, | |
| 403 typename X, | |
| 404 typename Y> | |
| 405 inline typename HashMap<T, U, V, W, X, Y>::iterator | |
| 406 HashMap<T, U, V, W, X, Y>::begin() { | |
| 407 return m_impl.begin(); | |
| 408 } | |
| 409 | |
| 410 template <typename T, | |
| 411 typename U, | |
| 412 typename V, | |
| 413 typename W, | |
| 414 typename X, | |
| 415 typename Y> | |
| 416 inline typename HashMap<T, U, V, W, X, Y>::iterator | |
| 417 HashMap<T, U, V, W, X, Y>::end() { | |
| 418 return m_impl.end(); | |
| 419 } | |
| 420 | |
| 421 template <typename T, | |
| 422 typename U, | |
| 423 typename V, | |
| 424 typename W, | |
| 425 typename X, | |
| 426 typename Y> | |
| 427 inline typename HashMap<T, U, V, W, X, Y>::const_iterator | |
| 428 HashMap<T, U, V, W, X, Y>::begin() const { | |
| 429 return m_impl.begin(); | |
| 430 } | |
| 431 | |
| 432 template <typename T, | |
| 433 typename U, | |
| 434 typename V, | |
| 435 typename W, | |
| 436 typename X, | |
| 437 typename Y> | |
| 438 inline typename HashMap<T, U, V, W, X, Y>::const_iterator | |
| 439 HashMap<T, U, V, W, X, Y>::end() const { | |
| 440 return m_impl.end(); | |
| 441 } | |
| 442 | |
| 443 template <typename T, | |
| 444 typename U, | |
| 445 typename V, | |
| 446 typename W, | |
| 447 typename X, | |
| 448 typename Y> | |
| 449 inline typename HashMap<T, U, V, W, X, Y>::iterator | |
| 450 HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key) { | |
| 451 return m_impl.find(key); | |
| 452 } | |
| 453 | |
| 454 template <typename T, | |
| 455 typename U, | |
| 456 typename V, | |
| 457 typename W, | |
| 458 typename X, | |
| 459 typename Y> | |
| 460 inline typename HashMap<T, U, V, W, X, Y>::const_iterator | |
| 461 HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key) const { | |
| 462 return m_impl.find(key); | |
| 463 } | |
| 464 | |
| 465 template <typename T, | |
| 466 typename U, | |
| 467 typename V, | |
| 468 typename W, | |
| 469 typename X, | |
| 470 typename Y> | |
| 471 inline bool HashMap<T, U, V, W, X, Y>::contains(KeyPeekInType key) const { | |
| 472 return m_impl.contains(key); | |
| 473 } | |
| 474 | |
| 475 template <typename T, | |
| 476 typename U, | |
| 477 typename V, | |
| 478 typename W, | |
| 479 typename X, | |
| 480 typename Y> | |
| 481 template <typename HashTranslator, typename TYPE> | |
| 482 inline typename HashMap<T, U, V, W, X, Y>::iterator | |
| 483 HashMap<T, U, V, W, X, Y>::find(const TYPE& value) { | |
| 484 return m_impl | |
| 485 .template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>( | |
| 486 value); | |
| 487 } | |
| 488 | |
| 489 template <typename T, | |
| 490 typename U, | |
| 491 typename V, | |
| 492 typename W, | |
| 493 typename X, | |
| 494 typename Y> | |
| 495 template <typename HashTranslator, typename TYPE> | |
| 496 inline typename HashMap<T, U, V, W, X, Y>::const_iterator | |
| 497 HashMap<T, U, V, W, X, Y>::find(const TYPE& value) const { | |
| 498 return m_impl | |
| 499 .template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>( | |
| 500 value); | |
| 501 } | |
| 502 | |
| 503 template <typename T, | |
| 504 typename U, | |
| 505 typename V, | |
| 506 typename W, | |
| 507 typename X, | |
| 508 typename Y> | |
| 509 template <typename HashTranslator, typename TYPE> | |
| 510 inline bool HashMap<T, U, V, W, X, Y>::contains(const TYPE& value) const { | |
| 511 return m_impl | |
| 512 .template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>( | |
| 513 value); | |
| 514 } | |
| 515 | |
| 516 template <typename T, | |
| 517 typename U, | |
| 518 typename V, | |
| 519 typename W, | |
| 520 typename X, | |
| 521 typename Y> | |
| 522 template <typename IncomingKeyType, typename IncomingMappedType> | |
| 523 typename HashMap<T, U, V, W, X, Y>::AddResult | |
| 524 HashMap<T, U, V, W, X, Y>::inlineAdd(IncomingKeyType&& key, | |
| 525 IncomingMappedType&& mapped) { | |
| 526 return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions>>( | |
| 527 std::forward<IncomingKeyType>(key), | |
| 528 std::forward<IncomingMappedType>(mapped)); | |
| 529 } | |
| 530 | |
| 531 template <typename T, | |
| 532 typename U, | |
| 533 typename V, | |
| 534 typename W, | |
| 535 typename X, | |
| 536 typename Y> | |
| 537 template <typename IncomingKeyType, typename IncomingMappedType> | |
| 538 typename HashMap<T, U, V, W, X, Y>::AddResult HashMap<T, U, V, W, X, Y>::set( | |
| 539 IncomingKeyType&& key, | |
| 540 IncomingMappedType&& mapped) { | |
| 541 AddResult result = inlineAdd(std::forward<IncomingKeyType>(key), | |
| 542 std::forward<IncomingMappedType>(mapped)); | |
| 543 if (!result.isNewEntry) { | |
| 544 // The inlineAdd call above found an existing hash table entry; we need | |
| 545 // to set the mapped value. | |
| 546 // | |
| 547 // It's safe to call std::forward again, because |mapped| isn't moved if | |
| 548 // there's an existing entry. | |
| 549 MappedTraits::store(std::forward<IncomingMappedType>(mapped), | |
| 550 result.storedValue->value); | |
| 551 } | |
| 552 return result; | |
| 553 } | |
| 554 | |
| 555 template <typename T, | |
| 556 typename U, | |
| 557 typename V, | |
| 558 typename W, | |
| 559 typename X, | |
| 560 typename Y> | |
| 561 template <typename HashTranslator, | |
| 562 typename IncomingKeyType, | |
| 563 typename IncomingMappedType> | |
| 564 auto HashMap<T, U, V, W, X, Y>::insert(IncomingKeyType&& key, | |
| 565 IncomingMappedType&& mapped) | |
| 566 -> AddResult { | |
| 567 return m_impl.template addPassingHashCode< | |
| 568 HashMapTranslatorAdapter<ValueTraits, HashTranslator>>( | |
| 569 std::forward<IncomingKeyType>(key), | |
| 570 std::forward<IncomingMappedType>(mapped)); | |
| 571 } | |
| 572 | |
| 573 template <typename T, | |
| 574 typename U, | |
| 575 typename V, | |
| 576 typename W, | |
| 577 typename X, | |
| 578 typename Y> | |
| 579 template <typename IncomingKeyType, typename IncomingMappedType> | |
| 580 typename HashMap<T, U, V, W, X, Y>::AddResult HashMap<T, U, V, W, X, Y>::insert( | |
| 581 IncomingKeyType&& key, | |
| 582 IncomingMappedType&& mapped) { | |
| 583 return inlineAdd(std::forward<IncomingKeyType>(key), | |
| 584 std::forward<IncomingMappedType>(mapped)); | |
| 585 } | |
| 586 | |
| 587 template <typename T, | |
| 588 typename U, | |
| 589 typename V, | |
| 590 typename W, | |
| 591 typename X, | |
| 592 typename Y> | |
| 593 typename HashMap<T, U, V, W, X, Y>::MappedPeekType | |
| 594 HashMap<T, U, V, W, X, Y>::at(KeyPeekInType key) const { | |
| 595 ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key); | |
| 596 if (!entry) | |
| 597 return MappedTraits::peek(MappedTraits::emptyValue()); | |
| 598 return MappedTraits::peek(entry->value); | |
| 599 } | |
| 600 | |
| 601 template <typename T, | |
| 602 typename U, | |
| 603 typename V, | |
| 604 typename W, | |
| 605 typename X, | |
| 606 typename Y> | |
| 607 inline void HashMap<T, U, V, W, X, Y>::erase(iterator it) { | |
| 608 m_impl.remove(it.m_impl); | |
| 609 } | |
| 610 | |
| 611 template <typename T, | |
| 612 typename U, | |
| 613 typename V, | |
| 614 typename W, | |
| 615 typename X, | |
| 616 typename Y> | |
| 617 inline void HashMap<T, U, V, W, X, Y>::erase(KeyPeekInType key) { | |
| 618 erase(find(key)); | |
| 619 } | |
| 620 | |
| 621 template <typename T, | |
| 622 typename U, | |
| 623 typename V, | |
| 624 typename W, | |
| 625 typename X, | |
| 626 typename Y> | |
| 627 inline void HashMap<T, U, V, W, X, Y>::clear() { | |
| 628 m_impl.clear(); | |
| 629 } | |
| 630 | |
| 631 template <typename T, | |
| 632 typename U, | |
| 633 typename V, | |
| 634 typename W, | |
| 635 typename X, | |
| 636 typename Y> | |
| 637 auto HashMap<T, U, V, W, X, Y>::take(KeyPeekInType key) -> MappedType { | |
| 638 iterator it = find(key); | |
| 639 if (it == end()) | |
| 640 return MappedTraits::emptyValue(); | |
| 641 MappedType result = std::move(it->value); | |
| 642 erase(it); | |
| 643 return result; | |
| 644 } | |
| 645 | |
| 646 template <typename T, | |
| 647 typename U, | |
| 648 typename V, | |
| 649 typename W, | |
| 650 typename X, | |
| 651 typename Y> | |
| 652 inline bool HashMap<T, U, V, W, X, Y>::isValidKey(KeyPeekInType key) { | |
| 653 if (KeyTraits::isDeletedValue(key)) | |
| 654 return false; | |
| 655 | |
| 656 if (HashFunctions::safeToCompareToEmptyOrDeleted) { | |
| 657 if (key == KeyTraits::emptyValue()) | |
| 658 return false; | |
| 659 } else { | |
| 660 if (isHashTraitsEmptyValue<KeyTraits>(key)) | |
| 661 return false; | |
| 662 } | |
| 663 | |
| 664 return true; | |
| 665 } | |
| 666 | |
| 667 template <typename T, | |
| 668 typename U, | |
| 669 typename V, | |
| 670 typename W, | |
| 671 typename X, | |
| 672 typename Y> | |
| 673 bool operator==(const HashMap<T, U, V, W, X, Y>& a, | |
| 674 const HashMap<T, U, V, W, X, Y>& b) { | |
| 675 if (a.size() != b.size()) | |
| 676 return false; | |
| 677 | |
| 678 typedef typename HashMap<T, U, V, W, X, Y>::const_iterator const_iterator; | |
| 679 | |
| 680 const_iterator aEnd = a.end(); | |
| 681 const_iterator bEnd = b.end(); | |
| 682 for (const_iterator it = a.begin(); it != aEnd; ++it) { | |
| 683 const_iterator bPos = b.find(it->key); | |
| 684 if (bPos == bEnd || it->value != bPos->value) | |
| 685 return false; | |
| 686 } | |
| 687 | |
| 688 return true; | |
| 689 } | |
| 690 | |
| 691 template <typename T, | |
| 692 typename U, | |
| 693 typename V, | |
| 694 typename W, | |
| 695 typename X, | |
| 696 typename Y> | |
| 697 inline bool operator!=(const HashMap<T, U, V, W, X, Y>& a, | |
| 698 const HashMap<T, U, V, W, X, Y>& b) { | |
| 699 return !(a == b); | |
| 700 } | |
| 701 | |
| 702 template <typename T, | |
| 703 typename U, | |
| 704 typename V, | |
| 705 typename W, | |
| 706 typename X, | |
| 707 typename Y, | |
| 708 typename Z> | |
| 709 inline void copyKeysToVector(const HashMap<T, U, V, W, X, Y>& collection, | |
| 710 Z& vector) { | |
| 711 typedef | |
| 712 typename HashMap<T, U, V, W, X, Y>::const_iterator::KeysIterator iterator; | |
| 713 | |
| 714 vector.resize(collection.size()); | |
| 715 | |
| 716 iterator it = collection.begin().keys(); | |
| 717 iterator end = collection.end().keys(); | |
| 718 for (unsigned i = 0; it != end; ++it, ++i) | |
| 719 vector[i] = *it; | |
| 720 } | |
| 721 | |
| 722 template <typename T, | |
| 723 typename U, | |
| 724 typename V, | |
| 725 typename W, | |
| 726 typename X, | |
| 727 typename Y, | |
| 728 typename Z> | |
| 729 inline void copyValuesToVector(const HashMap<T, U, V, W, X, Y>& collection, | |
| 730 Z& vector) { | |
| 731 typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::ValuesIterator | |
| 732 iterator; | |
| 733 | |
| 734 vector.resize(collection.size()); | |
| 735 | |
| 736 iterator it = collection.begin().values(); | |
| 737 iterator end = collection.end().values(); | |
| 738 for (unsigned i = 0; it != end; ++it, ++i) | |
| 739 vector[i] = *it; | |
| 740 } | |
| 741 | |
| 742 } // namespace WTF | |
| 743 | |
| 744 using WTF::HashMap; | |
| 745 | |
| 746 #endif // WTF_HashMap_h | |
| OLD | NEW |