2 * Copyright (C) 2005, 2006, 2007, 2008, 2011 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 "wtf/DefaultAllocator.h"
25 #include "wtf/HashTable.h"
29 template<typename KeyTraits, typename MappedTraits> struct HashMapValueTraits;
31 template<typename T> struct ReferenceTypeMaker {
32 typedef T& ReferenceType;
34 template<typename T> struct ReferenceTypeMaker<T&> {
35 typedef T& ReferenceType;
38 struct KeyValuePairKeyExtractor {
40 static const typename T::KeyType& extract(const T& p) { return p.key; }
46 typename HashArg = typename DefaultHash<KeyArg>::Hash,
47 typename KeyTraitsArg = HashTraits<KeyArg>,
48 typename MappedTraitsArg = HashTraits<MappedArg>,
49 typename Allocator = DefaultAllocator>
52 typedef KeyTraitsArg KeyTraits;
53 typedef MappedTraitsArg MappedTraits;
54 typedef HashMapValueTraits<KeyTraits, MappedTraits> ValueTraits;
57 typedef typename KeyTraits::TraitType KeyType;
58 typedef const typename KeyTraits::PeekInType& KeyPeekInType;
59 typedef typename MappedTraits::TraitType MappedType;
60 typedef typename ValueTraits::TraitType ValueType;
62 void* operator new(size_t size)
64 return Allocator::template malloc<void*, HashMap>(size);
66 void operator delete(void* p) { Allocator::free(p); }
67 void* operator new[](size_t size) { return Allocator::template newArray<HashMap>(size); }
68 void operator delete[](void* p) { Allocator::deleteArray(p); }
69 void* operator new(size_t, NotNullTag, void* location)
71 ASSERT(!Allocator::isGarbageCollected);
77 typedef typename MappedTraits::PassInType MappedPassInType;
78 typedef typename MappedTraits::PassOutType MappedPassOutType;
79 typedef typename MappedTraits::PeekOutType MappedPeekType;
81 typedef typename ReferenceTypeMaker<MappedPassInType>::ReferenceType MappedPassInReferenceType;
83 typedef HashArg HashFunctions;
85 typedef HashTable<KeyType, ValueType, KeyValuePairKeyExtractor,
86 HashFunctions, ValueTraits, KeyTraits, Allocator> HashTableType;
88 class HashMapKeysProxy;
89 class HashMapValuesProxy;
92 typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
93 typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
94 typedef typename HashTableType::AddResult AddResult;
97 void swap(HashMap& other)
99 m_impl.swap(other.m_impl);
102 unsigned size() const;
103 unsigned capacity() const;
104 bool isEmpty() const;
106 // iterators iterate over pairs of keys and values
109 const_iterator begin() const;
110 const_iterator end() const;
112 HashMapKeysProxy& keys() { return static_cast<HashMapKeysProxy&>(*this); }
113 const HashMapKeysProxy& keys() const { return static_cast<const HashMapKeysProxy&>(*this); }
115 HashMapValuesProxy& values() { return static_cast<HashMapValuesProxy&>(*this); }
116 const HashMapValuesProxy& values() const { return static_cast<const HashMapValuesProxy&>(*this); }
118 iterator find(KeyPeekInType);
119 const_iterator find(KeyPeekInType) const;
120 bool contains(KeyPeekInType) const;
121 MappedPeekType get(KeyPeekInType) const;
123 // replaces value but not key if key is already present
124 // return value is a pair of the iterator to the key location,
125 // and a boolean that's true if a new value was actually added
126 AddResult set(KeyPeekInType, MappedPassInType);
128 // does nothing if key is already present
129 // return value is a pair of the iterator to the key location,
130 // and a boolean that's true if a new value was actually added
131 AddResult add(KeyPeekInType, MappedPassInType);
133 void remove(KeyPeekInType);
134 void remove(iterator);
137 MappedPassOutType take(KeyPeekInType); // efficient combination of get with remove
139 // An alternate version of find() that finds the object by hashing and comparing
140 // with some other type, to avoid the cost of type conversion. HashTranslator
141 // must have the following function members:
142 // static unsigned hash(const T&);
143 // static bool equal(const ValueType&, const T&);
144 template<typename HashTranslator, typename T> iterator find(const T&);
145 template<typename HashTranslator, typename T> const_iterator find(const T&) const;
146 template<typename HashTranslator, typename T> bool contains(const T&) const;
148 // An alternate version of add() that finds the object by hashing and comparing
149 // with some other type, to avoid the cost of type conversion if the object is already
150 // in the table. HashTranslator must have the following function members:
151 // static unsigned hash(const T&);
152 // static bool equal(const ValueType&, const T&);
153 // static translate(ValueType&, const T&, unsigned hashCode);
154 template<typename HashTranslator, typename T> AddResult add(const T&, MappedPassInType);
156 static bool isValidKey(KeyPeekInType);
158 void trace(typename Allocator::Visitor* visitor)
160 m_impl.trace(visitor);
164 AddResult inlineAdd(KeyPeekInType, MappedPassInReferenceType);
166 HashTableType m_impl;
169 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg, typename Allocator>
170 class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator>::HashMapKeysProxy :
171 private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> {
173 typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> HashMapType;
174 typedef typename HashMapType::iterator::Keys iterator;
175 typedef typename HashMapType::const_iterator::Keys const_iterator;
179 return HashMapType::begin().keys();
184 return HashMapType::end().keys();
187 const_iterator begin() const
189 return HashMapType::begin().keys();
192 const_iterator end() const
194 return HashMapType::end().keys();
198 friend class HashMap;
200 // These are intentionally not implemented.
202 HashMapKeysProxy(const HashMapKeysProxy&);
203 HashMapKeysProxy& operator=(const HashMapKeysProxy&);
207 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg, typename Allocator>
208 class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator>::HashMapValuesProxy :
209 private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> {
211 typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> HashMapType;
212 typedef typename HashMapType::iterator::Values iterator;
213 typedef typename HashMapType::const_iterator::Values const_iterator;
217 return HashMapType::begin().values();
222 return HashMapType::end().values();
225 const_iterator begin() const
227 return HashMapType::begin().values();
230 const_iterator end() const
232 return HashMapType::end().values();
236 friend class HashMap;
238 // These are intentionally not implemented.
239 HashMapValuesProxy();
240 HashMapValuesProxy(const HashMapValuesProxy&);
241 HashMapValuesProxy& operator=(const HashMapValuesProxy&);
242 ~HashMapValuesProxy();
245 template<typename KeyTraits, typename MappedTraits> struct HashMapValueTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> {
246 static const bool hasIsEmptyValueFunction = true;
247 static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value)
249 return isHashTraitsEmptyValue<KeyTraits>(value.key);
253 template<typename ValueTraits, typename HashFunctions>
254 struct HashMapTranslator {
255 template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
256 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
257 template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped)
260 ValueTraits::ValueTraits::store(mapped, location.value);
264 template<typename ValueTraits, typename Translator>
265 struct HashMapTranslatorAdapter {
266 template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
267 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
268 template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped, unsigned hashCode)
270 Translator::translate(location.key, key, hashCode);
271 ValueTraits::ValueTraits::store(mapped, location.value);
275 template<typename T, typename U, typename V, typename W, typename X, typename Y>
276 inline unsigned HashMap<T, U, V, W, X, Y>::size() const
278 return m_impl.size();
281 template<typename T, typename U, typename V, typename W, typename X, typename Y>
282 inline unsigned HashMap<T, U, V, W, X, Y>::capacity() const
284 return m_impl.capacity();
287 template<typename T, typename U, typename V, typename W, typename X, typename Y>
288 inline bool HashMap<T, U, V, W, X, Y>::isEmpty() const
290 return m_impl.isEmpty();
293 template<typename T, typename U, typename V, typename W, typename X, typename Y>
294 inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::begin()
296 return m_impl.begin();
299 template<typename T, typename U, typename V, typename W, typename X, typename Y>
300 inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::end()
305 template<typename T, typename U, typename V, typename W, typename X, typename Y>
306 inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::begin() const
308 return m_impl.begin();
311 template<typename T, typename U, typename V, typename W, typename X, typename Y>
312 inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::end() const
317 template<typename T, typename U, typename V, typename W, typename X, typename Y>
318 inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key)
320 return m_impl.find(key);
323 template<typename T, typename U, typename V, typename W, typename X, typename Y>
324 inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key) const
326 return m_impl.find(key);
329 template<typename T, typename U, typename V, typename W, typename X, typename Y>
330 inline bool HashMap<T, U, V, W, X, Y>::contains(KeyPeekInType key) const
332 return m_impl.contains(key);
335 template<typename T, typename U, typename V, typename W, typename X, typename Y>
336 template<typename HashTranslator, typename TYPE>
337 inline typename HashMap<T, U, V, W, X, Y>::iterator
338 HashMap<T, U, V, W, X, Y>::find(const TYPE& value)
340 return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value);
343 template<typename T, typename U, typename V, typename W, typename X, typename Y>
344 template<typename HashTranslator, typename TYPE>
345 inline typename HashMap<T, U, V, W, X, Y>::const_iterator
346 HashMap<T, U, V, W, X, Y>::find(const TYPE& value) const
348 return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value);
351 template<typename T, typename U, typename V, typename W, typename X, typename Y>
352 template<typename HashTranslator, typename TYPE>
354 HashMap<T, U, V, W, X, Y>::contains(const TYPE& value) const
356 return m_impl.template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value);
359 template<typename T, typename U, typename V, typename W, typename X, typename Y>
360 typename HashMap<T, U, V, W, X, Y>::AddResult
361 HashMap<T, U, V, W, X, Y>::inlineAdd(KeyPeekInType key, MappedPassInReferenceType mapped)
363 return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions> >(key, mapped);
366 template<typename T, typename U, typename V, typename W, typename X, typename Y>
367 typename HashMap<T, U, V, W, X, Y>::AddResult
368 HashMap<T, U, V, W, X, Y>::set(KeyPeekInType key, MappedPassInType mapped)
370 AddResult result = inlineAdd(key, mapped);
371 if (!result.isNewEntry) {
372 // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
373 MappedTraits::store(mapped, result.iterator->value);
378 template<typename T, typename U, typename V, typename W, typename X, typename Y>
379 template<typename HashTranslator, typename TYPE>
380 typename HashMap<T, U, V, W, X, Y>::AddResult
381 HashMap<T, U, V, W, X, Y>::add(const TYPE& key, MappedPassInType value)
383 return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(key, value);
386 template<typename T, typename U, typename V, typename W, typename X, typename Y>
387 typename HashMap<T, U, V, W, X, Y>::AddResult
388 HashMap<T, U, V, W, X, Y>::add(KeyPeekInType key, MappedPassInType mapped)
390 return inlineAdd(key, mapped);
393 template<typename T, typename U, typename V, typename W, typename X, typename Y>
394 typename HashMap<T, U, V, W, X, Y>::MappedPeekType
395 HashMap<T, U, V, W, X, Y>::get(KeyPeekInType key) const
397 ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
399 return MappedTraits::peek(MappedTraits::emptyValue());
400 return MappedTraits::peek(entry->value);
403 template<typename T, typename U, typename V, typename W, typename X, typename Y>
404 inline void HashMap<T, U, V, W, X, Y>::remove(iterator it)
406 m_impl.remove(it.m_impl);
409 template<typename T, typename U, typename V, typename W, typename X, typename Y>
410 inline void HashMap<T, U, V, W, X, Y>::remove(KeyPeekInType key)
415 template<typename T, typename U, typename V, typename W, typename X, typename Y>
416 inline void HashMap<T, U, V, W, X, Y>::clear()
421 template<typename T, typename U, typename V, typename W, typename X, typename Y>
422 typename HashMap<T, U, V, W, X, Y>::MappedPassOutType
423 HashMap<T, U, V, W, X, Y>::take(KeyPeekInType key)
425 iterator it = find(key);
427 return MappedTraits::passOut(MappedTraits::emptyValue());
428 MappedPassOutType result = MappedTraits::passOut(it->value);
433 template<typename T, typename U, typename V, typename W, typename X, typename Y>
434 inline bool HashMap<T, U, V, W, X, Y>::isValidKey(KeyPeekInType key)
436 if (KeyTraits::isDeletedValue(key))
439 if (HashFunctions::safeToCompareToEmptyOrDeleted) {
440 if (key == KeyTraits::emptyValue())
443 if (isHashTraitsEmptyValue<KeyTraits>(key))
450 template<typename T, typename U, typename V, typename W, typename X, typename Y>
451 bool operator==(const HashMap<T, U, V, W, X, Y>& a, const HashMap<T, U, V, W, X, Y>& b)
453 if (a.size() != b.size())
456 typedef typename HashMap<T, U, V, W, X, Y>::const_iterator const_iterator;
458 const_iterator aEnd = a.end();
459 const_iterator bEnd = b.end();
460 for (const_iterator it = a.begin(); it != aEnd; ++it) {
461 const_iterator bPos = b.find(it->key);
462 if (bPos == bEnd || it->value != bPos->value)
469 template<typename T, typename U, typename V, typename W, typename X, typename Y>
470 inline bool operator!=(const HashMap<T, U, V, W, X, Y>& a, const HashMap<T, U, V, W, X, Y>& b)
475 template<typename T, typename U, typename V, typename W, typename X, typename Y>
476 inline void deleteAllValues(const HashMap<T, U, V, W, X, Y>& collection)
478 typedef typename HashMap<T, U, V, W, X, Y>::const_iterator iterator;
479 iterator end = collection.end();
480 for (iterator it = collection.begin(); it != end; ++it)
484 template<typename T, typename U, typename V, typename W, typename X, typename Y>
485 inline void deleteAllKeys(const HashMap<T, U, V, W, X, Y>& collection)
487 typedef typename HashMap<T, U, V, W, X, Y>::const_iterator iterator;
488 iterator end = collection.end();
489 for (iterator it = collection.begin(); it != end; ++it)
493 template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
494 inline void copyKeysToVector(const HashMap<T, U, V, W, X, Y>& collection, Z& vector)
496 typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::Keys iterator;
498 vector.resize(collection.size());
500 iterator it = collection.begin().keys();
501 iterator end = collection.end().keys();
502 for (unsigned i = 0; it != end; ++it, ++i)
506 template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
507 inline void copyValuesToVector(const HashMap<T, U, V, W, X, Y>& collection, Z& vector)
509 typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::Values iterator;
511 vector.resize(collection.size());
513 iterator it = collection.begin().values();
514 iterator end = collection.end().values();
515 for (unsigned i = 0; it != end; ++it, ++i)
523 #include "wtf/RefPtrHashMap.h"
525 #endif /* WTF_HashMap_h */