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
; }
43 // Note: empty or deleted key values are not allowed, using them may lead to undefined behavior.
44 // For pointer keys this means that null pointers are not allowed unless you supply custom key traits.
48 typename HashArg
= typename DefaultHash
<KeyArg
>::Hash
,
49 typename KeyTraitsArg
= HashTraits
<KeyArg
>,
50 typename MappedTraitsArg
= HashTraits
<MappedArg
>,
51 typename Allocator
= DefaultAllocator
>
53 WTF_USE_ALLOCATOR(HashMap
, Allocator
);
55 typedef KeyTraitsArg KeyTraits
;
56 typedef MappedTraitsArg MappedTraits
;
57 typedef HashMapValueTraits
<KeyTraits
, MappedTraits
> ValueTraits
;
60 typedef typename
KeyTraits::TraitType KeyType
;
61 typedef const typename
KeyTraits::PeekInType
& KeyPeekInType
;
62 typedef typename
MappedTraits::TraitType MappedType
;
63 typedef typename
ValueTraits::TraitType ValueType
;
66 typedef typename
MappedTraits::PassInType MappedPassInType
;
67 typedef typename
MappedTraits::PassOutType MappedPassOutType
;
68 typedef typename
MappedTraits::PeekOutType MappedPeekType
;
70 typedef typename ReferenceTypeMaker
<MappedPassInType
>::ReferenceType MappedPassInReferenceType
;
72 typedef HashArg HashFunctions
;
74 typedef HashTable
<KeyType
, ValueType
, KeyValuePairKeyExtractor
,
75 HashFunctions
, ValueTraits
, KeyTraits
, Allocator
> HashTableType
;
77 class HashMapKeysProxy
;
78 class HashMapValuesProxy
;
81 typedef HashTableIteratorAdapter
<HashTableType
, ValueType
> iterator
;
82 typedef HashTableConstIteratorAdapter
<HashTableType
, ValueType
> const_iterator
;
83 typedef typename
HashTableType::AddResult AddResult
;
86 void swap(HashMap
& ref
)
88 m_impl
.swap(ref
.m_impl
);
91 void swap(typename
Allocator::template OtherType
<HashMap
>::Type other
)
93 HashMap
& ref
= Allocator::getOther(other
);
94 m_impl
.swap(ref
.m_impl
);
97 unsigned size() const;
98 unsigned capacity() const;
101 // iterators iterate over pairs of keys and values
104 const_iterator
begin() const;
105 const_iterator
end() const;
107 HashMapKeysProxy
& keys() { return static_cast<HashMapKeysProxy
&>(*this); }
108 const HashMapKeysProxy
& keys() const { return static_cast<const HashMapKeysProxy
&>(*this); }
110 HashMapValuesProxy
& values() { return static_cast<HashMapValuesProxy
&>(*this); }
111 const HashMapValuesProxy
& values() const { return static_cast<const HashMapValuesProxy
&>(*this); }
113 iterator
find(KeyPeekInType
);
114 const_iterator
find(KeyPeekInType
) const;
115 bool contains(KeyPeekInType
) const;
116 MappedPeekType
get(KeyPeekInType
) const;
118 // replaces value but not key if key is already present
119 // return value is a pair of the iterator to the key location,
120 // and a boolean that's true if a new value was actually added
121 AddResult
set(KeyPeekInType
, MappedPassInType
);
123 // does nothing 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
add(KeyPeekInType
, MappedPassInType
);
128 void remove(KeyPeekInType
);
129 void remove(iterator
);
131 template<typename Collection
>
132 void removeAll(const Collection
& toBeRemoved
) { WTF::removeAll(*this, toBeRemoved
); }
134 MappedPassOutType
take(KeyPeekInType
); // efficient combination of get with remove
136 // An alternate version of find() that finds the object by hashing and comparing
137 // with some other type, to avoid the cost of type conversion. HashTranslator
138 // must have the following function members:
139 // static unsigned hash(const T&);
140 // static bool equal(const ValueType&, const T&);
141 template<typename HashTranslator
, typename T
> iterator
find(const T
&);
142 template<typename HashTranslator
, typename T
> const_iterator
find(const T
&) const;
143 template<typename HashTranslator
, typename T
> bool contains(const T
&) const;
145 // An alternate version of add() that finds the object by hashing and comparing
146 // with some other type, to avoid the cost of type conversion if the object is already
147 // in the table. HashTranslator must have the following function members:
148 // static unsigned hash(const T&);
149 // static bool equal(const ValueType&, const T&);
150 // static translate(ValueType&, const T&, unsigned hashCode);
151 template<typename HashTranslator
, typename T
> AddResult
add(const T
&, MappedPassInType
);
153 static bool isValidKey(KeyPeekInType
);
155 template<typename VisitorDispatcher
>
156 void trace(VisitorDispatcher visitor
) { m_impl
.trace(visitor
); }
159 AddResult
inlineAdd(KeyPeekInType
, MappedPassInReferenceType
);
161 HashTableType m_impl
;
164 template<typename KeyArg
, typename MappedArg
, typename HashArg
, typename KeyTraitsArg
, typename MappedTraitsArg
, typename Allocator
>
165 class HashMap
<KeyArg
, MappedArg
, HashArg
, KeyTraitsArg
, MappedTraitsArg
, Allocator
>::HashMapKeysProxy
:
166 private HashMap
<KeyArg
, MappedArg
, HashArg
, KeyTraitsArg
, MappedTraitsArg
, Allocator
> {
168 typedef HashMap
<KeyArg
, MappedArg
, HashArg
, KeyTraitsArg
, MappedTraitsArg
, Allocator
> HashMapType
;
169 typedef typename
HashMapType::iterator::Keys iterator
;
170 typedef typename
HashMapType::const_iterator::Keys const_iterator
;
174 return HashMapType::begin().keys();
179 return HashMapType::end().keys();
182 const_iterator
begin() const
184 return HashMapType::begin().keys();
187 const_iterator
end() const
189 return HashMapType::end().keys();
193 friend class HashMap
;
195 // These are intentionally not implemented.
197 HashMapKeysProxy(const HashMapKeysProxy
&);
198 HashMapKeysProxy
& operator=(const HashMapKeysProxy
&);
202 template<typename KeyArg
, typename MappedArg
, typename HashArg
, typename KeyTraitsArg
, typename MappedTraitsArg
, typename Allocator
>
203 class HashMap
<KeyArg
, MappedArg
, HashArg
, KeyTraitsArg
, MappedTraitsArg
, Allocator
>::HashMapValuesProxy
:
204 private HashMap
<KeyArg
, MappedArg
, HashArg
, KeyTraitsArg
, MappedTraitsArg
, Allocator
> {
206 typedef HashMap
<KeyArg
, MappedArg
, HashArg
, KeyTraitsArg
, MappedTraitsArg
, Allocator
> HashMapType
;
207 typedef typename
HashMapType::iterator::Values iterator
;
208 typedef typename
HashMapType::const_iterator::Values const_iterator
;
212 return HashMapType::begin().values();
217 return HashMapType::end().values();
220 const_iterator
begin() const
222 return HashMapType::begin().values();
225 const_iterator
end() const
227 return HashMapType::end().values();
231 friend class HashMap
;
233 // These are intentionally not implemented.
234 HashMapValuesProxy();
235 HashMapValuesProxy(const HashMapValuesProxy
&);
236 HashMapValuesProxy
& operator=(const HashMapValuesProxy
&);
237 ~HashMapValuesProxy();
240 template<typename KeyTraits
, typename MappedTraits
> struct HashMapValueTraits
: KeyValuePairHashTraits
<KeyTraits
, MappedTraits
> {
241 static const bool hasIsEmptyValueFunction
= true;
242 static bool isEmptyValue(const typename KeyValuePairHashTraits
<KeyTraits
, MappedTraits
>::TraitType
& value
)
244 return isHashTraitsEmptyValue
<KeyTraits
>(value
.key
);
248 template<typename ValueTraits
, typename HashFunctions
>
249 struct HashMapTranslator
{
250 template<typename T
> static unsigned hash(const T
& key
) { return HashFunctions::hash(key
); }
251 template<typename T
, typename U
> static bool equal(const T
& a
, const U
& b
) { return HashFunctions::equal(a
, b
); }
252 template<typename T
, typename U
, typename V
> static void translate(T
& location
, const U
& key
, const V
& mapped
)
255 ValueTraits::ValueTraits::store(mapped
, location
.value
);
259 template<typename ValueTraits
, typename Translator
>
260 struct HashMapTranslatorAdapter
{
261 template<typename T
> static unsigned hash(const T
& key
) { return Translator::hash(key
); }
262 template<typename T
, typename U
> static bool equal(const T
& a
, const U
& b
) { return Translator::equal(a
, b
); }
263 template<typename T
, typename U
, typename V
> static void translate(T
& location
, const U
& key
, const V
& mapped
, unsigned hashCode
)
265 Translator::translate(location
.key
, key
, hashCode
);
266 ValueTraits::ValueTraits::store(mapped
, location
.value
);
270 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
271 inline unsigned HashMap
<T
, U
, V
, W
, X
, Y
>::size() const
273 return m_impl
.size();
276 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
277 inline unsigned HashMap
<T
, U
, V
, W
, X
, Y
>::capacity() const
279 return m_impl
.capacity();
282 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
283 inline bool HashMap
<T
, U
, V
, W
, X
, Y
>::isEmpty() const
285 return m_impl
.isEmpty();
288 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
289 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::iterator HashMap
<T
, U
, V
, W
, X
, Y
>::begin()
291 return m_impl
.begin();
294 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
295 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::iterator HashMap
<T
, U
, V
, W
, X
, Y
>::end()
300 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
301 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::const_iterator HashMap
<T
, U
, V
, W
, X
, Y
>::begin() const
303 return m_impl
.begin();
306 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
307 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::const_iterator HashMap
<T
, U
, V
, W
, X
, Y
>::end() const
312 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
313 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::iterator HashMap
<T
, U
, V
, W
, X
, Y
>::find(KeyPeekInType key
)
315 return m_impl
.find(key
);
318 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
319 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::const_iterator HashMap
<T
, U
, V
, W
, X
, Y
>::find(KeyPeekInType key
) const
321 return m_impl
.find(key
);
324 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
325 inline bool HashMap
<T
, U
, V
, W
, X
, Y
>::contains(KeyPeekInType key
) const
327 return m_impl
.contains(key
);
330 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
331 template<typename HashTranslator
, typename TYPE
>
332 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::iterator
333 HashMap
<T
, U
, V
, W
, X
, Y
>::find(const TYPE
& value
)
335 return m_impl
.template find
<HashMapTranslatorAdapter
<ValueTraits
, HashTranslator
>>(value
);
338 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
339 template<typename HashTranslator
, typename TYPE
>
340 inline typename HashMap
<T
, U
, V
, W
, X
, Y
>::const_iterator
341 HashMap
<T
, U
, V
, W
, X
, Y
>::find(const TYPE
& value
) const
343 return m_impl
.template find
<HashMapTranslatorAdapter
<ValueTraits
, HashTranslator
>>(value
);
346 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
347 template<typename HashTranslator
, typename TYPE
>
349 HashMap
<T
, U
, V
, W
, X
, Y
>::contains(const TYPE
& value
) const
351 return m_impl
.template contains
<HashMapTranslatorAdapter
<ValueTraits
, HashTranslator
>>(value
);
354 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
355 typename HashMap
<T
, U
, V
, W
, X
, Y
>::AddResult
356 HashMap
<T
, U
, V
, W
, X
, Y
>::inlineAdd(KeyPeekInType key
, MappedPassInReferenceType mapped
)
358 return m_impl
.template add
<HashMapTranslator
<ValueTraits
, HashFunctions
>>(key
, mapped
);
361 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
362 typename HashMap
<T
, U
, V
, W
, X
, Y
>::AddResult
363 HashMap
<T
, U
, V
, W
, X
, Y
>::set(KeyPeekInType key
, MappedPassInType mapped
)
365 AddResult result
= inlineAdd(key
, mapped
);
366 if (!result
.isNewEntry
) {
367 // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
368 MappedTraits::store(mapped
, result
.storedValue
->value
);
373 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
374 template<typename HashTranslator
, typename TYPE
>
375 typename HashMap
<T
, U
, V
, W
, X
, Y
>::AddResult
376 HashMap
<T
, U
, V
, W
, X
, Y
>::add(const TYPE
& key
, MappedPassInType value
)
378 return m_impl
.template addPassingHashCode
<HashMapTranslatorAdapter
<ValueTraits
, HashTranslator
>>(key
, value
);
381 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
382 typename HashMap
<T
, U
, V
, W
, X
, Y
>::AddResult
383 HashMap
<T
, U
, V
, W
, X
, Y
>::add(KeyPeekInType key
, MappedPassInType mapped
)
385 return inlineAdd(key
, mapped
);
388 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
389 typename HashMap
<T
, U
, V
, W
, X
, Y
>::MappedPeekType
390 HashMap
<T
, U
, V
, W
, X
, Y
>::get(KeyPeekInType key
) const
392 ValueType
* entry
= const_cast<HashTableType
&>(m_impl
).lookup(key
);
394 return MappedTraits::peek(MappedTraits::emptyValue());
395 return MappedTraits::peek(entry
->value
);
398 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
399 inline void HashMap
<T
, U
, V
, W
, X
, Y
>::remove(iterator it
)
401 m_impl
.remove(it
.m_impl
);
404 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
405 inline void HashMap
<T
, U
, V
, W
, X
, Y
>::remove(KeyPeekInType key
)
410 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
411 inline void HashMap
<T
, U
, V
, W
, X
, Y
>::clear()
416 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
417 typename HashMap
<T
, U
, V
, W
, X
, Y
>::MappedPassOutType
418 HashMap
<T
, U
, V
, W
, X
, Y
>::take(KeyPeekInType key
)
420 iterator it
= find(key
);
422 return MappedTraits::passOut(MappedTraits::emptyValue());
423 MappedPassOutType result
= MappedTraits::passOut(it
->value
);
428 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
429 inline bool HashMap
<T
, U
, V
, W
, X
, Y
>::isValidKey(KeyPeekInType key
)
431 if (KeyTraits::isDeletedValue(key
))
434 if (HashFunctions::safeToCompareToEmptyOrDeleted
) {
435 if (key
== KeyTraits::emptyValue())
438 if (isHashTraitsEmptyValue
<KeyTraits
>(key
))
445 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
446 bool operator==(const HashMap
<T
, U
, V
, W
, X
, Y
>& a
, const HashMap
<T
, U
, V
, W
, X
, Y
>& b
)
448 if (a
.size() != b
.size())
451 typedef typename HashMap
<T
, U
, V
, W
, X
, Y
>::const_iterator const_iterator
;
453 const_iterator aEnd
= a
.end();
454 const_iterator bEnd
= b
.end();
455 for (const_iterator it
= a
.begin(); it
!= aEnd
; ++it
) {
456 const_iterator bPos
= b
.find(it
->key
);
457 if (bPos
== bEnd
|| it
->value
!= bPos
->value
)
464 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
>
465 inline bool operator!=(const HashMap
<T
, U
, V
, W
, X
, Y
>& a
, const HashMap
<T
, U
, V
, W
, X
, Y
>& b
)
470 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
, typename Z
>
471 inline void copyKeysToVector(const HashMap
<T
, U
, V
, W
, X
, Y
>& collection
, Z
& vector
)
473 typedef typename HashMap
<T
, U
, V
, W
, X
, Y
>::const_iterator::Keys iterator
;
475 vector
.resize(collection
.size());
477 iterator it
= collection
.begin().keys();
478 iterator end
= collection
.end().keys();
479 for (unsigned i
= 0; it
!= end
; ++it
, ++i
)
483 template<typename T
, typename U
, typename V
, typename W
, typename X
, typename Y
, typename Z
>
484 inline void copyValuesToVector(const HashMap
<T
, U
, V
, W
, X
, Y
>& collection
, Z
& vector
)
486 typedef typename HashMap
<T
, U
, V
, W
, X
, Y
>::const_iterator::Values iterator
;
488 vector
.resize(collection
.size());
490 iterator it
= collection
.begin().values();
491 iterator end
= collection
.end().values();
492 for (unsigned i
= 0; it
!= end
; ++it
, ++i
)
497 template<typename T
, typename U
, typename V
, typename W
, typename X
>
498 struct NeedsTracing
<HashMap
<T
, U
, V
, W
, X
>> {
499 static const bool value
= false;
507 #endif /* WTF_HashMap_h */