• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
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 
21 #ifndef WTF_HashMap_h
22 #define WTF_HashMap_h
23 
24 #include "HashTable.h"
25 
26 namespace WTF {
27 
28     template<typename PairType> struct PairFirstExtractor;
29 
30     template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
31         typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> >
32     class HashMap : public FastAllocBase {
33     private:
34         typedef KeyTraitsArg KeyTraits;
35         typedef MappedTraitsArg MappedTraits;
36         typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
37 
38     public:
39         typedef typename KeyTraits::TraitType KeyType;
40         typedef typename MappedTraits::TraitType MappedType;
41         typedef typename ValueTraits::TraitType ValueType;
42 
43     private:
44         typedef HashArg HashFunctions;
45 
46         typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
47             HashFunctions, ValueTraits, KeyTraits> HashTableType;
48 
49     public:
50         typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
51         typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
52 
53         void swap(HashMap&);
54 
55         int size() const;
56         int capacity() const;
57         bool isEmpty() const;
58 
59         // iterators iterate over pairs of keys and values
60         iterator begin();
61         iterator end();
62         const_iterator begin() const;
63         const_iterator end() const;
64 
65         iterator find(const KeyType&);
66         const_iterator find(const KeyType&) const;
67         bool contains(const KeyType&) const;
68         MappedType get(const KeyType&) const;
69 
70         // replaces value but not key if key is already present
71         // return value is a pair of the iterator to the key location,
72         // and a boolean that's true if a new value was actually added
73         pair<iterator, bool> set(const KeyType&, const MappedType&);
74 
75         // does nothing if key is already present
76         // return value is a pair of the iterator to the key location,
77         // and a boolean that's true if a new value was actually added
78         pair<iterator, bool> add(const KeyType&, const MappedType&);
79 
80         void remove(const KeyType&);
81         void remove(iterator);
82         void clear();
83 
84         MappedType take(const KeyType&); // efficient combination of get with remove
85 
86     private:
87         pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
88 
89         HashTableType m_impl;
90     };
91 
92     template<typename PairType> struct PairFirstExtractor {
extractPairFirstExtractor93         static const typename PairType::first_type& extract(const PairType& p) { return p.first; }
94     };
95 
96     template<typename ValueType, typename ValueTraits, typename HashFunctions>
97     struct HashMapTranslator {
98         typedef typename ValueType::first_type KeyType;
99         typedef typename ValueType::second_type MappedType;
100 
hashHashMapTranslator101         static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
equalHashMapTranslator102         static bool equal(const KeyType& a, const KeyType& b) { return HashFunctions::equal(a, b); }
translateHashMapTranslator103         static void translate(ValueType& location, const KeyType& key, const MappedType& mapped)
104         {
105             location.first = key;
106             location.second = mapped;
107         }
108     };
109 
110     template<typename T, typename U, typename V, typename W, typename X>
swap(HashMap & other)111     inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
112     {
113         m_impl.swap(other.m_impl);
114     }
115 
116     template<typename T, typename U, typename V, typename W, typename X>
size()117     inline int HashMap<T, U, V, W, X>::size() const
118     {
119         return m_impl.size();
120     }
121 
122     template<typename T, typename U, typename V, typename W, typename X>
capacity()123     inline int HashMap<T, U, V, W, X>::capacity() const
124     {
125         return m_impl.capacity();
126     }
127 
128     template<typename T, typename U, typename V, typename W, typename X>
isEmpty()129     inline bool HashMap<T, U, V, W, X>::isEmpty() const
130     {
131         return m_impl.isEmpty();
132     }
133 
134     template<typename T, typename U, typename V, typename W, typename X>
begin()135     inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::begin()
136     {
137         return m_impl.begin();
138     }
139 
140     template<typename T, typename U, typename V, typename W, typename X>
end()141     inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::end()
142     {
143         return m_impl.end();
144     }
145 
146     template<typename T, typename U, typename V, typename W, typename X>
begin()147     inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::begin() const
148     {
149         return m_impl.begin();
150     }
151 
152     template<typename T, typename U, typename V, typename W, typename X>
end()153     inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::end() const
154     {
155         return m_impl.end();
156     }
157 
158     template<typename T, typename U, typename V, typename W, typename X>
find(const KeyType & key)159     inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const KeyType& key)
160     {
161         return m_impl.find(key);
162     }
163 
164     template<typename T, typename U, typename V, typename W, typename X>
find(const KeyType & key)165     inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const KeyType& key) const
166     {
167         return m_impl.find(key);
168     }
169 
170     template<typename T, typename U, typename V, typename W, typename X>
contains(const KeyType & key)171     inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const
172     {
173         return m_impl.contains(key);
174     }
175 
176     template<typename T, typename U, typename V, typename W, typename X>
177     inline pair<typename HashMap<T, U, V, W, X>::iterator, bool>
inlineAdd(const KeyType & key,const MappedType & mapped)178     HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped)
179     {
180         typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
181         return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
182     }
183 
184     template<typename T, typename U, typename V, typename W, typename X>
185     pair<typename HashMap<T, U, V, W, X>::iterator, bool>
set(const KeyType & key,const MappedType & mapped)186     HashMap<T, U, V, W, X>::set(const KeyType& key, const MappedType& mapped)
187     {
188         pair<iterator, bool> result = inlineAdd(key, mapped);
189         if (!result.second) {
190             // add call above didn't change anything, so set the mapped value
191             result.first->second = mapped;
192         }
193         return result;
194     }
195 
196     template<typename T, typename U, typename V, typename W, typename X>
197     pair<typename HashMap<T, U, V, W, X>::iterator, bool>
add(const KeyType & key,const MappedType & mapped)198     HashMap<T, U, V, W, X>::add(const KeyType& key, const MappedType& mapped)
199     {
200         return inlineAdd(key, mapped);
201     }
202 
203     template<typename T, typename U, typename V, typename W, typename MappedTraits>
204     typename HashMap<T, U, V, W, MappedTraits>::MappedType
get(const KeyType & key)205     HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const
206     {
207         ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
208         if (!entry)
209             return MappedTraits::emptyValue();
210         return entry->second;
211     }
212 
213     template<typename T, typename U, typename V, typename W, typename X>
remove(iterator it)214     inline void HashMap<T, U, V, W, X>::remove(iterator it)
215     {
216         if (it.m_impl == m_impl.end())
217             return;
218         m_impl.checkTableConsistency();
219         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
220     }
221 
222     template<typename T, typename U, typename V, typename W, typename X>
remove(const KeyType & key)223     inline void HashMap<T, U, V, W, X>::remove(const KeyType& key)
224     {
225         remove(find(key));
226     }
227 
228     template<typename T, typename U, typename V, typename W, typename X>
clear()229     inline void HashMap<T, U, V, W, X>::clear()
230     {
231         m_impl.clear();
232     }
233 
234     template<typename T, typename U, typename V, typename W, typename MappedTraits>
235     typename HashMap<T, U, V, W, MappedTraits>::MappedType
take(const KeyType & key)236     HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key)
237     {
238         // This can probably be made more efficient to avoid ref/deref churn.
239         iterator it = find(key);
240         if (it == end())
241             return MappedTraits::emptyValue();
242         typename HashMap<T, U, V, W, MappedTraits>::MappedType result = it->second;
243         remove(it);
244         return result;
245     }
246 
247     template<typename T, typename U, typename V, typename W, typename X>
248     bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
249     {
250         if (a.size() != b.size())
251             return false;
252 
253         typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator;
254 
255         const_iterator end = a.end();
256         const_iterator notFound = b.end();
257         for (const_iterator it = a.begin(); it != end; ++it) {
258             const_iterator bPos = b.find(it->first);
259             if (bPos == notFound || it->second != bPos->second)
260                 return false;
261         }
262 
263         return true;
264     }
265 
266     template<typename T, typename U, typename V, typename W, typename X>
267     inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
268     {
269         return !(a == b);
270     }
271 
272     template<typename MappedType, typename HashTableType>
deleteAllPairSeconds(HashTableType & collection)273     void deleteAllPairSeconds(HashTableType& collection)
274     {
275         typedef typename HashTableType::const_iterator iterator;
276         iterator end = collection.end();
277         for (iterator it = collection.begin(); it != end; ++it)
278             delete it->second;
279     }
280 
281     template<typename T, typename U, typename V, typename W, typename X>
deleteAllValues(const HashMap<T,U,V,W,X> & collection)282     inline void deleteAllValues(const HashMap<T, U, V, W, X>& collection)
283     {
284         deleteAllPairSeconds<typename HashMap<T, U, V, W, X>::MappedType>(collection);
285     }
286 
287     template<typename KeyType, typename HashTableType>
deleteAllPairFirsts(HashTableType & collection)288     void deleteAllPairFirsts(HashTableType& collection)
289     {
290         typedef typename HashTableType::const_iterator iterator;
291         iterator end = collection.end();
292         for (iterator it = collection.begin(); it != end; ++it)
293             delete it->first;
294     }
295 
296     template<typename T, typename U, typename V, typename W, typename X>
deleteAllKeys(const HashMap<T,U,V,W,X> & collection)297     inline void deleteAllKeys(const HashMap<T, U, V, W, X>& collection)
298     {
299         deleteAllPairFirsts<typename HashMap<T, U, V, W, X>::KeyType>(collection);
300     }
301 
302     template<typename T, typename U, typename V, typename W, typename X, typename Y>
copyKeysToVector(const HashMap<T,U,V,W,X> & collection,Y & vector)303     inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
304     {
305         typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator;
306 
307         vector.resize(collection.size());
308 
309         iterator it = collection.begin().keys();
310         iterator end = collection.end().keys();
311         for (unsigned i = 0; it != end; ++it, ++i)
312             vector[i] = *it;
313     }
314 
315     template<typename T, typename U, typename V, typename W, typename X, typename Y>
copyValuesToVector(const HashMap<T,U,V,W,X> & collection,Y & vector)316     inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
317     {
318         typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator;
319 
320         vector.resize(collection.size());
321 
322         iterator it = collection.begin().values();
323         iterator end = collection.end().values();
324         for (unsigned i = 0; it != end; ++it, ++i)
325             vector[i] = *it;
326     }
327 
328 } // namespace WTF
329 
330 using WTF::HashMap;
331 
332 #include "RefPtrHashMap.h"
333 
334 #endif /* WTF_HashMap_h */
335