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 |