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/HashTable.h>
26 #include <wtf/IteratorRange.h>
30 template<typename T> struct KeyValuePairKeyExtractor {
31 static const typename T::KeyType& extract(const T& p) { return p.key; }
34 template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
35 typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg>>
37 WTF_MAKE_FAST_ALLOCATED;
39 typedef KeyTraitsArg KeyTraits;
40 typedef MappedTraitsArg MappedTraits;
42 struct KeyValuePairTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> {
43 static const bool hasIsEmptyValueFunction = true;
44 static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value)
46 return isHashTraitsEmptyValue<KeyTraits>(value.key);
51 typedef typename KeyTraits::TraitType KeyType;
52 typedef typename MappedTraits::TraitType MappedType;
53 typedef typename KeyValuePairTraits::TraitType KeyValuePairType;
56 typedef typename MappedTraits::PeekType MappedPeekType;
58 typedef HashArg HashFunctions;
60 typedef HashTable<KeyType, KeyValuePairType, KeyValuePairKeyExtractor<KeyValuePairType>,
61 HashFunctions, KeyValuePairTraits, KeyTraits> HashTableType;
63 class HashMapKeysProxy;
64 class HashMapValuesProxy;
67 typedef HashTableIteratorAdapter<HashTableType, KeyValuePairType> iterator;
68 typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePairType> const_iterator;
69 typedef typename HashTableType::AddResult AddResult;
76 HashMap(std::initializer_list<KeyValuePairType> initializerList)
78 for (const auto& keyValuePair : initializerList)
79 add(keyValuePair.key, keyValuePair.value);
88 // iterators iterate over pairs of keys and values
91 const_iterator begin() const;
92 const_iterator end() const;
94 IteratorRange<typename iterator::Keys> keys() { return makeIteratorRange(begin().keys(), end().keys()); }
95 const IteratorRange<typename const_iterator::Keys> keys() const { return makeIteratorRange(begin().keys(), end().keys()); }
97 IteratorRange<typename iterator::Values> values() { return makeIteratorRange(begin().values(), end().values()); }
98 const IteratorRange<typename const_iterator::Values> values() const { return makeIteratorRange(begin().values(), end().values()); }
100 iterator find(const KeyType&);
101 const_iterator find(const KeyType&) const;
102 bool contains(const KeyType&) const;
103 MappedPeekType get(const KeyType&) const;
105 // Replaces the value but not the key if the key is already present.
106 // Return value includes both an iterator to the key location,
107 // and an isNewEntry boolean that's true if a new entry was added.
108 template<typename V> AddResult set(const KeyType&, V&&);
109 template<typename V> AddResult set(KeyType&&, V&&);
111 // Does nothing if the key is already present.
112 // Return value includes both an iterator to the key location,
113 // and an isNewEntry boolean that's true if a new entry was added.
114 template<typename V> AddResult add(const KeyType&, V&&);
115 template<typename V> AddResult add(KeyType&&, V&&);
117 // Same as add(), but aggressively inlined.
118 template<typename V> AddResult fastAdd(const KeyType&, V&&);
119 template<typename V> AddResult fastAdd(KeyType&&, V&&);
121 bool remove(const KeyType&);
122 bool remove(iterator);
123 template<typename Functor>
124 void removeIf(const Functor& functor);
127 MappedType take(const KeyType&); // efficient combination of get with remove
129 // An alternate version of find() that finds the object by hashing and comparing
130 // with some other type, to avoid the cost of type conversion. HashTranslator
131 // must have the following function members:
132 // static unsigned hash(const T&);
133 // static bool equal(const ValueType&, const T&);
134 template<typename HashTranslator, typename T> iterator find(const T&);
135 template<typename HashTranslator, typename T> const_iterator find(const T&) const;
136 template<typename HashTranslator, typename T> bool contains(const T&) const;
138 // An alternate version of add() that finds the object by hashing and comparing
139 // with some other type, to avoid the cost of type conversion if the object is already
140 // in the table. HashTranslator must have the following function members:
141 // static unsigned hash(const T&);
142 // static bool equal(const ValueType&, const T&);
143 // static translate(ValueType&, const T&, unsigned hashCode);
144 template<typename HashTranslator, typename K, typename V> AddResult add(K&&, V&&);
146 void checkConsistency() const;
148 static bool isValidKey(const KeyType&);
151 template<typename K, typename V>
152 AddResult inlineSet(K&&, V&&);
154 template<typename K, typename V>
155 AddResult inlineAdd(K&&, V&&);
157 HashTableType m_impl;
160 template<typename ValueTraits, typename HashFunctions>
161 struct HashMapTranslator {
162 template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
163 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
164 template<typename T, typename U, typename V> static void translate(T& location, U&& key, V&& mapped)
166 location.key = std::forward<U>(key);
167 location.value = std::forward<V>(mapped);
171 template<typename ValueTraits, typename Translator>
172 struct HashMapTranslatorAdapter {
173 template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
174 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
175 template<typename T, typename U, typename V> static void translate(T& location, U&& key, V&& mapped, unsigned hashCode)
177 Translator::translate(location.key, key, hashCode);
178 location.value = std::forward<V>(mapped);
182 template<typename T, typename U, typename V, typename W, typename X>
183 inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
185 m_impl.swap(other.m_impl);
188 template<typename T, typename U, typename V, typename W, typename X>
189 inline int HashMap<T, U, V, W, X>::size() const
191 return m_impl.size();
194 template<typename T, typename U, typename V, typename W, typename X>
195 inline int HashMap<T, U, V, W, X>::capacity() const
197 return m_impl.capacity();
200 template<typename T, typename U, typename V, typename W, typename X>
201 inline bool HashMap<T, U, V, W, X>::isEmpty() const
203 return m_impl.isEmpty();
206 template<typename T, typename U, typename V, typename W, typename X>
207 inline auto HashMap<T, U, V, W, X>::begin() -> iterator
209 return m_impl.begin();
212 template<typename T, typename U, typename V, typename W, typename X>
213 inline auto HashMap<T, U, V, W, X>::end() -> iterator
218 template<typename T, typename U, typename V, typename W, typename X>
219 inline auto HashMap<T, U, V, W, X>::begin() const -> const_iterator
221 return m_impl.begin();
224 template<typename T, typename U, typename V, typename W, typename X>
225 inline auto HashMap<T, U, V, W, X>::end() const -> const_iterator
230 template<typename T, typename U, typename V, typename W, typename X>
231 inline auto HashMap<T, U, V, W, X>::find(const KeyType& key) -> iterator
233 return m_impl.find(key);
236 template<typename T, typename U, typename V, typename W, typename X>
237 inline auto HashMap<T, U, V, W, X>::find(const KeyType& key) const -> const_iterator
239 return m_impl.find(key);
242 template<typename T, typename U, typename V, typename W, typename X>
243 inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const
245 return m_impl.contains(key);
248 template<typename T, typename U, typename V, typename W, typename X>
249 template<typename HashTranslator, typename TYPE>
250 inline typename HashMap<T, U, V, W, X>::iterator
251 HashMap<T, U, V, W, X>::find(const TYPE& value)
253 return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
256 template<typename T, typename U, typename V, typename W, typename X>
257 template<typename HashTranslator, typename TYPE>
258 inline typename HashMap<T, U, V, W, X>::const_iterator
259 HashMap<T, U, V, W, X>::find(const TYPE& value) const
261 return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
264 template<typename T, typename U, typename V, typename W, typename X>
265 template<typename HashTranslator, typename TYPE>
266 inline bool HashMap<T, U, V, W, X>::contains(const TYPE& value) const
268 return m_impl.template contains<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
271 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
272 template<typename K, typename V>
273 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::inlineSet(K&& key, V&& value) -> AddResult
275 AddResult result = inlineAdd(std::forward<K>(key), std::forward<V>(value));
276 if (!result.isNewEntry) {
277 // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
278 result.iterator->value = std::forward<V>(value);
283 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
284 template<typename K, typename V>
285 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::inlineAdd(K&& key, V&& value) -> AddResult
287 return m_impl.template add<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(std::forward<K>(key), std::forward<V>(value));
290 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
292 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(const KeyType& key, T&& mapped) -> AddResult
294 return inlineSet(key, std::forward<T>(mapped));
297 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
299 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(KeyType&& key, T&& mapped) -> AddResult
301 return inlineSet(WTF::move(key), std::forward<T>(mapped));
304 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
305 template<typename HashTranslator, typename K, typename V>
306 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(K&& key, V&& value) -> AddResult
308 return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(std::forward<K>(key), std::forward<V>(value));
311 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
313 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(const KeyType& key, T&& mapped) -> AddResult
315 return inlineAdd(key, std::forward<T>(mapped));
318 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
320 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(KeyType&& key, T&& mapped) -> AddResult
322 return inlineAdd(WTF::move(key), std::forward<T>(mapped));
325 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
327 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(const KeyType& key, T&& mapped) -> AddResult
329 return inlineAdd(key, std::forward<T>(mapped));
332 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
334 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(KeyType&& key, T&& mapped) -> AddResult
336 return inlineAdd(WTF::move(key), std::forward<T>(mapped));
339 template<typename T, typename U, typename V, typename W, typename MappedTraits>
340 auto HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const -> MappedPeekType
342 KeyValuePairType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
344 return MappedTraits::peek(MappedTraits::emptyValue());
345 return MappedTraits::peek(entry->value);
348 template<typename T, typename U, typename V, typename W, typename X>
349 inline bool HashMap<T, U, V, W, X>::remove(iterator it)
351 if (it.m_impl == m_impl.end())
353 m_impl.internalCheckTableConsistency();
354 m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
358 template<typename T, typename U, typename V, typename W, typename X>
359 template<typename Functor>
360 inline void HashMap<T, U, V, W, X>::removeIf(const Functor& functor)
362 m_impl.removeIf(functor);
365 template<typename T, typename U, typename V, typename W, typename X>
366 inline bool HashMap<T, U, V, W, X>::remove(const KeyType& key)
368 return remove(find(key));
371 template<typename T, typename U, typename V, typename W, typename X>
372 inline void HashMap<T, U, V, W, X>::clear()
377 template<typename T, typename U, typename V, typename W, typename MappedTraits>
378 auto HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key) -> MappedType
380 iterator it = find(key);
382 return MappedTraits::emptyValue();
383 MappedType value = WTF::move(it->value);
388 template<typename T, typename U, typename V, typename W, typename X>
389 inline void HashMap<T, U, V, W, X>::checkConsistency() const
391 m_impl.checkTableConsistency();
394 template<typename T, typename U, typename V, typename W, typename X>
395 inline bool HashMap<T, U, V, W, X>::isValidKey(const KeyType& key)
397 if (KeyTraits::isDeletedValue(key))
400 if (HashFunctions::safeToCompareToEmptyOrDeleted) {
401 if (key == KeyTraits::emptyValue())
404 if (isHashTraitsEmptyValue<KeyTraits>(key))
411 template<typename T, typename U, typename V, typename W, typename X>
412 bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
414 if (a.size() != b.size())
417 typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator;
419 const_iterator end = a.end();
420 const_iterator notFound = b.end();
421 for (const_iterator it = a.begin(); it != end; ++it) {
422 const_iterator bPos = b.find(it->key);
423 if (bPos == notFound || it->value != bPos->value)
430 template<typename T, typename U, typename V, typename W, typename X>
431 inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
436 template<typename T, typename U, typename V, typename W, typename X, typename Y>
437 inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
439 typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator;
441 vector.resize(collection.size());
443 iterator it = collection.begin().keys();
444 iterator end = collection.end().keys();
445 for (unsigned i = 0; it != end; ++it, ++i)
449 template<typename T, typename U, typename V, typename W, typename X, typename Y>
450 inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
452 typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator;
454 vector.resize(collection.size());
456 iterator it = collection.begin().values();
457 iterator end = collection.end().values();
458 for (unsigned i = 0; it != end; ++it, ++i)
466 #include <wtf/RefPtrHashMap.h>
468 #endif /* WTF_HashMap_h */