3fc81af0b260e3a6e84c655d5473a6c4a223ac31
[WebKit-https.git] / Source / WTF / wtf / HashMap.h
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013 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 <initializer_list>
25 #include <wtf/HashTable.h>
26 #include <wtf/IteratorRange.h>
27
28 namespace WTF {
29
30 template<typename T> struct KeyValuePairKeyExtractor {
31     static const typename T::KeyType& extract(const T& p) { return p.key; }
32 };
33
34 template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
35     typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg>>
36 class HashMap final {
37     WTF_MAKE_FAST_ALLOCATED;
38 private:
39     typedef KeyTraitsArg KeyTraits;
40     typedef MappedTraitsArg MappedTraits;
41
42     struct KeyValuePairTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> {
43         static const bool hasIsEmptyValueFunction = true;
44         static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value)
45         {
46             return isHashTraitsEmptyValue<KeyTraits>(value.key);
47         }
48     };
49
50 public:
51     typedef typename KeyTraits::TraitType KeyType;
52     typedef typename MappedTraits::TraitType MappedType;
53     typedef typename KeyValuePairTraits::TraitType KeyValuePairType;
54
55 private:
56     typedef typename MappedTraits::PeekType MappedPeekType;
57
58     typedef HashArg HashFunctions;
59
60     typedef HashTable<KeyType, KeyValuePairType, KeyValuePairKeyExtractor<KeyValuePairType>,
61         HashFunctions, KeyValuePairTraits, KeyTraits> HashTableType;
62
63     class HashMapKeysProxy;
64     class HashMapValuesProxy;
65
66 public:
67     typedef HashTableIteratorAdapter<HashTableType, KeyValuePairType> iterator;
68     typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePairType> const_iterator;
69     typedef typename HashTableType::AddResult AddResult;
70
71 public:
72     HashMap()
73     {
74     }
75
76     HashMap(std::initializer_list<KeyValuePairType> initializerList)
77     {
78         for (const auto& keyValuePair : initializerList)
79             add(keyValuePair.key, keyValuePair.value);
80     }
81
82     void swap(HashMap&);
83
84     int size() const;
85     int capacity() const;
86     bool isEmpty() const;
87
88     // iterators iterate over pairs of keys and values
89     iterator begin();
90     iterator end();
91     const_iterator begin() const;
92     const_iterator end() const;
93
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()); }
96
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()); }
99
100     iterator find(const KeyType&);
101     const_iterator find(const KeyType&) const;
102     bool contains(const KeyType&) const;
103     MappedPeekType get(const KeyType&) const;
104
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&&);
110
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&&);
116
117     // Same as add(), but aggressively inlined.
118     template<typename V> AddResult fastAdd(const KeyType&, V&&);
119     template<typename V> AddResult fastAdd(KeyType&&, V&&);
120
121     bool remove(const KeyType&);
122     bool remove(iterator);
123     template<typename Functor>
124     void removeIf(const Functor& functor);
125     void clear();
126
127     MappedType take(const KeyType&); // efficient combination of get with remove
128
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;
137
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&&);
145
146     void checkConsistency() const;
147
148     static bool isValidKey(const KeyType&);
149
150 private:
151     template<typename K, typename V>
152     AddResult inlineSet(K&&, V&&);
153
154     template<typename K, typename V>
155     AddResult inlineAdd(K&&, V&&);
156
157     HashTableType m_impl;
158 };
159
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)
165     {
166         location.key = std::forward<U>(key);
167         location.value = std::forward<V>(mapped);
168     }
169 };
170
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)
176     {
177         Translator::translate(location.key, key, hashCode);
178         location.value = std::forward<V>(mapped);
179     }
180 };
181
182 template<typename T, typename U, typename V, typename W, typename X>
183 inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
184 {
185     m_impl.swap(other.m_impl); 
186 }
187
188 template<typename T, typename U, typename V, typename W, typename X>
189 inline int HashMap<T, U, V, W, X>::size() const
190 {
191     return m_impl.size(); 
192 }
193
194 template<typename T, typename U, typename V, typename W, typename X>
195 inline int HashMap<T, U, V, W, X>::capacity() const
196
197     return m_impl.capacity(); 
198 }
199
200 template<typename T, typename U, typename V, typename W, typename X>
201 inline bool HashMap<T, U, V, W, X>::isEmpty() const
202 {
203     return m_impl.isEmpty();
204 }
205
206 template<typename T, typename U, typename V, typename W, typename X>
207 inline auto HashMap<T, U, V, W, X>::begin() -> iterator
208 {
209     return m_impl.begin();
210 }
211
212 template<typename T, typename U, typename V, typename W, typename X>
213 inline auto HashMap<T, U, V, W, X>::end() -> iterator
214 {
215     return m_impl.end();
216 }
217
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
220 {
221     return m_impl.begin();
222 }
223
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
226 {
227     return m_impl.end();
228 }
229
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
232 {
233     return m_impl.find(key);
234 }
235
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
238 {
239     return m_impl.find(key);
240 }
241
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
244 {
245     return m_impl.contains(key);
246 }
247
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)
252 {
253     return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
254 }
255
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
260 {
261     return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
262 }
263
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
267 {
268     return m_impl.template contains<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
269 }
270
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
274 {
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);
279     }
280     return result;
281 }
282
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
286 {
287     return m_impl.template add<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(std::forward<K>(key), std::forward<V>(value));
288 }
289
290 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
291 template<typename T>
292 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(const KeyType& key, T&& mapped) -> AddResult
293 {
294     return inlineSet(key, std::forward<T>(mapped));
295 }
296
297 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
298 template<typename T>
299 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(KeyType&& key, T&& mapped) -> AddResult
300 {
301     return inlineSet(WTF::move(key), std::forward<T>(mapped));
302 }
303
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
307 {
308     return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(std::forward<K>(key), std::forward<V>(value));
309 }
310
311 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
312 template<typename T>
313 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(const KeyType& key, T&& mapped) -> AddResult
314 {
315     return inlineAdd(key, std::forward<T>(mapped));
316 }
317
318 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
319 template<typename T>
320 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(KeyType&& key, T&& mapped) -> AddResult
321 {
322     return inlineAdd(WTF::move(key), std::forward<T>(mapped));
323 }
324
325 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
326 template<typename T>
327 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(const KeyType& key, T&& mapped) -> AddResult
328 {
329     return inlineAdd(key, std::forward<T>(mapped));
330 }
331
332 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
333 template<typename T>
334 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(KeyType&& key, T&& mapped) -> AddResult
335 {
336     return inlineAdd(WTF::move(key), std::forward<T>(mapped));
337 }
338
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
341 {
342     KeyValuePairType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
343     if (!entry)
344         return MappedTraits::peek(MappedTraits::emptyValue());
345     return MappedTraits::peek(entry->value);
346 }
347
348 template<typename T, typename U, typename V, typename W, typename X>
349 inline bool HashMap<T, U, V, W, X>::remove(iterator it)
350 {
351     if (it.m_impl == m_impl.end())
352         return false;
353     m_impl.internalCheckTableConsistency();
354     m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
355     return true;
356 }
357
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)
361 {
362     m_impl.removeIf(functor);
363 }
364
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)
367 {
368     return remove(find(key));
369 }
370
371 template<typename T, typename U, typename V, typename W, typename X>
372 inline void HashMap<T, U, V, W, X>::clear()
373 {
374     m_impl.clear();
375 }
376
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
379 {
380     iterator it = find(key);
381     if (it == end())
382         return MappedTraits::emptyValue();
383     MappedType value = WTF::move(it->value);
384     remove(it);
385     return value;
386 }
387
388 template<typename T, typename U, typename V, typename W, typename X>
389 inline void HashMap<T, U, V, W, X>::checkConsistency() const
390 {
391     m_impl.checkTableConsistency();
392 }
393
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)
396 {
397     if (KeyTraits::isDeletedValue(key))
398         return false;
399
400     if (HashFunctions::safeToCompareToEmptyOrDeleted) {
401         if (key == KeyTraits::emptyValue())
402             return false;
403     } else {
404         if (isHashTraitsEmptyValue<KeyTraits>(key))
405             return false;
406     }
407
408     return true;
409 }
410
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)
413 {
414     if (a.size() != b.size())
415         return false;
416
417     typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator;
418
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)
424             return false;
425     }
426
427     return true;
428 }
429
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)
432 {
433     return !(a == b);
434 }
435
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)
438 {
439     typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator;
440     
441     vector.resize(collection.size());
442     
443     iterator it = collection.begin().keys();
444     iterator end = collection.end().keys();
445     for (unsigned i = 0; it != end; ++it, ++i)
446         vector[i] = *it;
447 }  
448
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)
451 {
452     typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator;
453     
454     vector.resize(collection.size());
455     
456     iterator it = collection.begin().values();
457     iterator end = collection.end().values();
458     for (unsigned i = 0; it != end; ++it, ++i)
459         vector[i] = *it;
460 }   
461
462 } // namespace WTF
463
464 using WTF::HashMap;
465
466 #include <wtf/RefPtrHashMap.h>
467
468 #endif /* WTF_HashMap_h */