2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013 Apple Inc. All rights reserved.
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.
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.
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.
24 #include <initializer_list>
25 #include <wtf/GetPtr.h>
26 #include <wtf/HashTable.h>
27 #include <wtf/IteratorRange.h>
31 template<typename T> struct KeyValuePairKeyExtractor {
32 static const typename T::KeyType& extract(const T& p) { return p.key; }
35 template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
36 typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg>>
38 WTF_MAKE_FAST_ALLOCATED;
40 typedef KeyTraitsArg KeyTraits;
41 typedef MappedTraitsArg MappedTraits;
43 struct KeyValuePairTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> {
44 static const bool hasIsEmptyValueFunction = true;
45 static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value)
47 return isHashTraitsEmptyValue<KeyTraits>(value.key);
52 typedef typename KeyTraits::TraitType KeyType;
53 typedef typename MappedTraits::TraitType MappedType;
54 typedef typename KeyValuePairTraits::TraitType KeyValuePairType;
57 typedef typename MappedTraits::PeekType MappedPeekType;
59 typedef HashArg HashFunctions;
61 typedef HashTable<KeyType, KeyValuePairType, KeyValuePairKeyExtractor<KeyValuePairType>,
62 HashFunctions, KeyValuePairTraits, KeyTraits> HashTableType;
64 class HashMapKeysProxy;
65 class HashMapValuesProxy;
68 typedef HashTableIteratorAdapter<HashTableType, KeyValuePairType> iterator;
69 typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePairType> const_iterator;
70 typedef typename HashTableType::AddResult AddResult;
77 HashMap(std::initializer_list<KeyValuePairType> initializerList)
79 for (const auto& keyValuePair : initializerList)
80 add(keyValuePair.key, keyValuePair.value);
89 // iterators iterate over pairs of keys and values
92 const_iterator begin() const;
93 const_iterator end() const;
95 IteratorRange<typename iterator::Keys> keys() { return makeIteratorRange(begin().keys(), end().keys()); }
96 const IteratorRange<typename const_iterator::Keys> keys() const { return makeIteratorRange(begin().keys(), end().keys()); }
98 IteratorRange<typename iterator::Values> values() { return makeIteratorRange(begin().values(), end().values()); }
99 const IteratorRange<typename const_iterator::Values> values() const { return makeIteratorRange(begin().values(), end().values()); }
101 iterator find(const KeyType&);
102 const_iterator find(const KeyType&) const;
103 bool contains(const KeyType&) const;
104 MappedPeekType get(const KeyType&) const;
106 // Replaces the value but not the key if the key is already present.
107 // Return value includes both an iterator to the key location,
108 // and an isNewEntry boolean that's true if a new entry was added.
109 template<typename V> AddResult set(const KeyType&, V&&);
110 template<typename V> AddResult set(KeyType&&, V&&);
112 // Does nothing if the key is already present.
113 // Return value includes both an iterator to the key location,
114 // and an isNewEntry boolean that's true if a new entry was added.
115 template<typename V> AddResult add(const KeyType&, V&&);
116 template<typename V> AddResult add(KeyType&&, V&&);
118 // Same as add(), but aggressively inlined.
119 template<typename V> AddResult fastAdd(const KeyType&, V&&);
120 template<typename V> AddResult fastAdd(KeyType&&, V&&);
122 bool remove(const KeyType&);
123 bool remove(iterator);
124 template<typename Functor>
125 void removeIf(const Functor& functor);
128 MappedType take(const KeyType&); // efficient combination of get with remove
130 // An alternate version of find() that finds the object by hashing and comparing
131 // with some other type, to avoid the cost of type conversion. HashTranslator
132 // must have the following function members:
133 // static unsigned hash(const T&);
134 // static bool equal(const ValueType&, const T&);
135 template<typename HashTranslator, typename T> iterator find(const T&);
136 template<typename HashTranslator, typename T> const_iterator find(const T&) const;
137 template<typename HashTranslator, typename T> bool contains(const T&) const;
139 // An alternate version of add() that finds the object by hashing and comparing
140 // with some other type, to avoid the cost of type conversion if the object is already
141 // in the table. HashTranslator must have the following function members:
142 // static unsigned hash(const T&);
143 // static bool equal(const ValueType&, const T&);
144 // static translate(ValueType&, const T&, unsigned hashCode);
145 template<typename HashTranslator, typename K, typename V> AddResult add(K&&, V&&);
147 // Overloads for smart pointer keys that take the raw pointer type as the parameter.
148 template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, iterator>::type find(typename GetPtrHelper<K>::PtrType);
149 template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, const_iterator>::type find(typename GetPtrHelper<K>::PtrType) const;
150 template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, bool>::type contains(typename GetPtrHelper<K>::PtrType) const;
151 template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, MappedPeekType>::type get(typename GetPtrHelper<K>::PtrType) const;
152 template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, bool>::type remove(typename GetPtrHelper<K>::PtrType);
153 template<typename K = KeyType> typename std::enable_if<IsSmartPtr<K>::value, MappedType>::type take(typename GetPtrHelper<K>::PtrType);
155 void checkConsistency() const;
157 static bool isValidKey(const KeyType&);
160 template<typename K, typename V>
161 AddResult inlineSet(K&&, V&&);
163 template<typename K, typename V>
164 AddResult inlineAdd(K&&, V&&);
166 HashTableType m_impl;
169 template<typename ValueTraits, typename HashFunctions>
170 struct HashMapTranslator {
171 template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
172 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
173 template<typename T, typename U, typename V> static void translate(T& location, U&& key, V&& mapped)
175 location.key = std::forward<U>(key);
176 location.value = std::forward<V>(mapped);
180 template<typename ValueTraits, typename Translator>
181 struct HashMapTranslatorAdapter {
182 template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
183 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
184 template<typename T, typename U, typename V> static void translate(T& location, U&& key, V&& mapped, unsigned hashCode)
186 Translator::translate(location.key, key, hashCode);
187 location.value = std::forward<V>(mapped);
191 template<typename T, typename U, typename V, typename W, typename X>
192 inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
194 m_impl.swap(other.m_impl);
197 template<typename T, typename U, typename V, typename W, typename X>
198 inline int HashMap<T, U, V, W, X>::size() const
200 return m_impl.size();
203 template<typename T, typename U, typename V, typename W, typename X>
204 inline int HashMap<T, U, V, W, X>::capacity() const
206 return m_impl.capacity();
209 template<typename T, typename U, typename V, typename W, typename X>
210 inline bool HashMap<T, U, V, W, X>::isEmpty() const
212 return m_impl.isEmpty();
215 template<typename T, typename U, typename V, typename W, typename X>
216 inline auto HashMap<T, U, V, W, X>::begin() -> iterator
218 return m_impl.begin();
221 template<typename T, typename U, typename V, typename W, typename X>
222 inline auto HashMap<T, U, V, W, X>::end() -> iterator
227 template<typename T, typename U, typename V, typename W, typename X>
228 inline auto HashMap<T, U, V, W, X>::begin() const -> const_iterator
230 return m_impl.begin();
233 template<typename T, typename U, typename V, typename W, typename X>
234 inline auto HashMap<T, U, V, W, X>::end() const -> const_iterator
239 template<typename T, typename U, typename V, typename W, typename X>
240 inline auto HashMap<T, U, V, W, X>::find(const KeyType& key) -> iterator
242 return m_impl.find(key);
245 template<typename T, typename U, typename V, typename W, typename X>
246 inline auto HashMap<T, U, V, W, X>::find(const KeyType& key) const -> const_iterator
248 return m_impl.find(key);
251 template<typename T, typename U, typename V, typename W, typename X>
252 inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const
254 return m_impl.contains(key);
257 template<typename T, typename U, typename V, typename W, typename X>
258 template<typename HashTranslator, typename TYPE>
259 inline typename HashMap<T, U, V, W, X>::iterator
260 HashMap<T, U, V, W, X>::find(const TYPE& value)
262 return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
265 template<typename T, typename U, typename V, typename W, typename X>
266 template<typename HashTranslator, typename TYPE>
267 inline typename HashMap<T, U, V, W, X>::const_iterator
268 HashMap<T, U, V, W, X>::find(const TYPE& value) const
270 return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
273 template<typename T, typename U, typename V, typename W, typename X>
274 template<typename HashTranslator, typename TYPE>
275 inline bool HashMap<T, U, V, W, X>::contains(const TYPE& value) const
277 return m_impl.template contains<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
280 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
281 template<typename K, typename V>
282 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::inlineSet(K&& key, V&& value) -> AddResult
284 AddResult result = inlineAdd(std::forward<K>(key), std::forward<V>(value));
285 if (!result.isNewEntry) {
286 // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
287 result.iterator->value = std::forward<V>(value);
292 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
293 template<typename K, typename V>
294 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::inlineAdd(K&& key, V&& value) -> AddResult
296 return m_impl.template add<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(std::forward<K>(key), std::forward<V>(value));
299 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
301 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(const KeyType& key, T&& mapped) -> AddResult
303 return inlineSet(key, std::forward<T>(mapped));
306 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
308 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(KeyType&& key, T&& mapped) -> AddResult
310 return inlineSet(WTF::move(key), std::forward<T>(mapped));
313 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
314 template<typename HashTranslator, typename K, typename V>
315 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(K&& key, V&& value) -> AddResult
317 return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(std::forward<K>(key), std::forward<V>(value));
320 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
322 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(const KeyType& key, T&& mapped) -> AddResult
324 return inlineAdd(key, std::forward<T>(mapped));
327 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
329 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(KeyType&& key, T&& mapped) -> AddResult
331 return inlineAdd(WTF::move(key), std::forward<T>(mapped));
334 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
336 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(const KeyType& key, T&& mapped) -> AddResult
338 return inlineAdd(key, std::forward<T>(mapped));
341 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
343 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(KeyType&& key, T&& mapped) -> AddResult
345 return inlineAdd(WTF::move(key), std::forward<T>(mapped));
348 template<typename T, typename U, typename V, typename W, typename MappedTraits>
349 auto HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const -> MappedPeekType
351 KeyValuePairType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
353 return MappedTraits::peek(MappedTraits::emptyValue());
354 return MappedTraits::peek(entry->value);
357 template<typename T, typename U, typename V, typename W, typename X>
358 inline bool HashMap<T, U, V, W, X>::remove(iterator it)
360 if (it.m_impl == m_impl.end())
362 m_impl.internalCheckTableConsistency();
363 m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
367 template<typename T, typename U, typename V, typename W, typename X>
368 template<typename Functor>
369 inline void HashMap<T, U, V, W, X>::removeIf(const Functor& functor)
371 m_impl.removeIf(functor);
374 template<typename T, typename U, typename V, typename W, typename X>
375 inline bool HashMap<T, U, V, W, X>::remove(const KeyType& key)
377 return remove(find(key));
380 template<typename T, typename U, typename V, typename W, typename X>
381 inline void HashMap<T, U, V, W, X>::clear()
386 template<typename T, typename U, typename V, typename W, typename MappedTraits>
387 auto HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key) -> MappedType
389 iterator it = find(key);
391 return MappedTraits::emptyValue();
392 MappedType value = WTF::move(it->value);
397 template<typename T, typename U, typename V, typename W, typename X>
399 inline auto HashMap<T, U, V, W, X>::find(typename GetPtrHelper<K>::PtrType key) -> typename std::enable_if<IsSmartPtr<K>::value, iterator>::type
401 return m_impl.template find<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
404 template<typename T, typename U, typename V, typename W, typename X>
406 inline auto HashMap<T, U, V, W, X>::find(typename GetPtrHelper<K>::PtrType key) const -> typename std::enable_if<IsSmartPtr<K>::value, const_iterator>::type
408 return m_impl.template find<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
411 template<typename T, typename U, typename V, typename W, typename X>
413 inline auto HashMap<T, U, V, W, X>::contains(typename GetPtrHelper<K>::PtrType key) const -> typename std::enable_if<IsSmartPtr<K>::value, bool>::type
415 return m_impl.template contains<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
418 template<typename T, typename U, typename V, typename W, typename X>
420 inline auto HashMap<T, U, V, W, X>::get(typename GetPtrHelper<K>::PtrType key) const -> typename std::enable_if<IsSmartPtr<K>::value, MappedPeekType>::type
422 KeyValuePairType* entry = const_cast<HashTableType&>(m_impl).template lookup<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(key);
424 return MappedTraits::peek(MappedTraits::emptyValue());
425 return MappedTraits::peek(entry->value);
428 template<typename T, typename U, typename V, typename W, typename X>
430 inline auto HashMap<T, U, V, W, X>::remove(typename GetPtrHelper<K>::PtrType key) -> typename std::enable_if<IsSmartPtr<K>::value, bool>::type
432 return remove(find(key));
435 template<typename T, typename U, typename V, typename W, typename X>
437 inline auto HashMap<T, U, V, W, X>::take(typename GetPtrHelper<K>::PtrType key) -> typename std::enable_if<IsSmartPtr<K>::value, MappedType>::type
439 iterator it = find(key);
441 return MappedTraits::emptyValue();
442 MappedType value = WTF::move(it->value);
447 template<typename T, typename U, typename V, typename W, typename X>
448 inline void HashMap<T, U, V, W, X>::checkConsistency() const
450 m_impl.checkTableConsistency();
453 template<typename T, typename U, typename V, typename W, typename X>
454 inline bool HashMap<T, U, V, W, X>::isValidKey(const KeyType& key)
456 if (KeyTraits::isDeletedValue(key))
459 if (HashFunctions::safeToCompareToEmptyOrDeleted) {
460 if (key == KeyTraits::emptyValue())
463 if (isHashTraitsEmptyValue<KeyTraits>(key))
470 template<typename T, typename U, typename V, typename W, typename X>
471 bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
473 if (a.size() != b.size())
476 typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator;
478 const_iterator end = a.end();
479 const_iterator notFound = b.end();
480 for (const_iterator it = a.begin(); it != end; ++it) {
481 const_iterator bPos = b.find(it->key);
482 if (bPos == notFound || it->value != bPos->value)
489 template<typename T, typename U, typename V, typename W, typename X>
490 inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
495 template<typename T, typename U, typename V, typename W, typename X, typename Y>
496 inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
498 typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator;
500 vector.resize(collection.size());
502 iterator it = collection.begin().keys();
503 iterator end = collection.end().keys();
504 for (unsigned i = 0; it != end; ++it, ++i)
508 template<typename T, typename U, typename V, typename W, typename X, typename Y>
509 inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
511 typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator;
513 vector.resize(collection.size());
515 iterator it = collection.begin().values();
516 iterator end = collection.end().values();
517 for (unsigned i = 0; it != end; ++it, ++i)
525 #include <wtf/RefPtrHashMap.h>
527 #endif /* WTF_HashMap_h */