Add WTF::move()
[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 {
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     void clear();
124
125     MappedType take(const KeyType&); // efficient combination of get with remove
126
127     // An alternate version of find() that finds the object by hashing and comparing
128     // with some other type, to avoid the cost of type conversion. HashTranslator
129     // must have the following function members:
130     //   static unsigned hash(const T&);
131     //   static bool equal(const ValueType&, const T&);
132     template<typename HashTranslator, typename T> iterator find(const T&);
133     template<typename HashTranslator, typename T> const_iterator find(const T&) const;
134     template<typename HashTranslator, typename T> bool contains(const T&) const;
135
136     // An alternate version of add() that finds the object by hashing and comparing
137     // with some other type, to avoid the cost of type conversion if the object is already
138     // in the table. HashTranslator must have the following function members:
139     //   static unsigned hash(const T&);
140     //   static bool equal(const ValueType&, const T&);
141     //   static translate(ValueType&, const T&, unsigned hashCode);
142     template<typename HashTranslator, typename K, typename V> AddResult add(K&&, V&&);
143
144     void checkConsistency() const;
145
146     static bool isValidKey(const KeyType&);
147
148 private:
149     template<typename K, typename V>
150     AddResult inlineSet(K&&, V&&);
151
152     template<typename K, typename V>
153     AddResult inlineAdd(K&&, V&&);
154
155     HashTableType m_impl;
156 };
157
158 template<typename ValueTraits, typename HashFunctions>
159 struct HashMapTranslator {
160     template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
161     template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
162     template<typename T, typename U, typename V> static void translate(T& location, U&& key, V&& mapped)
163     {
164         location.key = std::forward<U>(key);
165         location.value = std::forward<V>(mapped);
166     }
167 };
168
169 template<typename ValueTraits, typename Translator>
170 struct HashMapTranslatorAdapter {
171     template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
172     template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
173     template<typename T, typename U, typename V> static void translate(T& location, U&& key, V&& mapped, unsigned hashCode)
174     {
175         Translator::translate(location.key, key, hashCode);
176         location.value = std::forward<V>(mapped);
177     }
178 };
179
180 template<typename T, typename U, typename V, typename W, typename X>
181 inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
182 {
183     m_impl.swap(other.m_impl); 
184 }
185
186 template<typename T, typename U, typename V, typename W, typename X>
187 inline int HashMap<T, U, V, W, X>::size() const
188 {
189     return m_impl.size(); 
190 }
191
192 template<typename T, typename U, typename V, typename W, typename X>
193 inline int HashMap<T, U, V, W, X>::capacity() const
194
195     return m_impl.capacity(); 
196 }
197
198 template<typename T, typename U, typename V, typename W, typename X>
199 inline bool HashMap<T, U, V, W, X>::isEmpty() const
200 {
201     return m_impl.isEmpty();
202 }
203
204 template<typename T, typename U, typename V, typename W, typename X>
205 inline auto HashMap<T, U, V, W, X>::begin() -> iterator
206 {
207     return m_impl.begin();
208 }
209
210 template<typename T, typename U, typename V, typename W, typename X>
211 inline auto HashMap<T, U, V, W, X>::end() -> iterator
212 {
213     return m_impl.end();
214 }
215
216 template<typename T, typename U, typename V, typename W, typename X>
217 inline auto HashMap<T, U, V, W, X>::begin() const -> const_iterator
218 {
219     return m_impl.begin();
220 }
221
222 template<typename T, typename U, typename V, typename W, typename X>
223 inline auto HashMap<T, U, V, W, X>::end() const -> const_iterator
224 {
225     return m_impl.end();
226 }
227
228 template<typename T, typename U, typename V, typename W, typename X>
229 inline auto HashMap<T, U, V, W, X>::find(const KeyType& key) -> iterator
230 {
231     return m_impl.find(key);
232 }
233
234 template<typename T, typename U, typename V, typename W, typename X>
235 inline auto HashMap<T, U, V, W, X>::find(const KeyType& key) const -> const_iterator
236 {
237     return m_impl.find(key);
238 }
239
240 template<typename T, typename U, typename V, typename W, typename X>
241 inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const
242 {
243     return m_impl.contains(key);
244 }
245
246 template<typename T, typename U, typename V, typename W, typename X>
247 template<typename HashTranslator, typename TYPE>
248 inline typename HashMap<T, U, V, W, X>::iterator
249 HashMap<T, U, V, W, X>::find(const TYPE& value)
250 {
251     return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
252 }
253
254 template<typename T, typename U, typename V, typename W, typename X>
255 template<typename HashTranslator, typename TYPE>
256 inline typename HashMap<T, U, V, W, X>::const_iterator 
257 HashMap<T, U, V, W, X>::find(const TYPE& value) const
258 {
259     return m_impl.template find<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
260 }
261
262 template<typename T, typename U, typename V, typename W, typename X>
263 template<typename HashTranslator, typename TYPE>
264 inline bool HashMap<T, U, V, W, X>::contains(const TYPE& value) const
265 {
266     return m_impl.template contains<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
267 }
268
269 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
270 template<typename K, typename V>
271 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::inlineSet(K&& key, V&& value) -> AddResult
272 {
273     AddResult result = inlineAdd(std::forward<K>(key), std::forward<V>(value));
274     if (!result.isNewEntry) {
275         // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
276         result.iterator->value = std::forward<V>(value);
277     }
278     return result;
279 }
280
281 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
282 template<typename K, typename V>
283 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::inlineAdd(K&& key, V&& value) -> AddResult
284 {
285     return m_impl.template add<HashMapTranslator<KeyValuePairTraits, HashFunctions>>(std::forward<K>(key), std::forward<V>(value));
286 }
287
288 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
289 template<typename T>
290 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(const KeyType& key, T&& mapped) -> AddResult
291 {
292     return inlineSet(key, std::forward<T>(mapped));
293 }
294
295 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
296 template<typename T>
297 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(KeyType&& key, T&& mapped) -> AddResult
298 {
299     return inlineSet(WTF::move(key), std::forward<T>(mapped));
300 }
301
302 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
303 template<typename HashTranslator, typename K, typename V>
304 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(K&& key, V&& value) -> AddResult
305 {
306     return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(std::forward<K>(key), std::forward<V>(value));
307 }
308
309 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
310 template<typename T>
311 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(const KeyType& key, T&& mapped) -> AddResult
312 {
313     return inlineAdd(key, std::forward<T>(mapped));
314 }
315
316 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
317 template<typename T>
318 auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::add(KeyType&& key, T&& mapped) -> AddResult
319 {
320     return inlineAdd(WTF::move(key), std::forward<T>(mapped));
321 }
322
323 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
324 template<typename T>
325 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(const KeyType& key, T&& mapped) -> AddResult
326 {
327     return inlineAdd(key, std::forward<T>(mapped));
328 }
329
330 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
331 template<typename T>
332 ALWAYS_INLINE auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::fastAdd(KeyType&& key, T&& mapped) -> AddResult
333 {
334     return inlineAdd(WTF::move(key), std::forward<T>(mapped));
335 }
336
337 template<typename T, typename U, typename V, typename W, typename MappedTraits>
338 auto HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const -> MappedPeekType
339 {
340     KeyValuePairType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
341     if (!entry)
342         return MappedTraits::peek(MappedTraits::emptyValue());
343     return MappedTraits::peek(entry->value);
344 }
345
346 template<typename T, typename U, typename V, typename W, typename X>
347 inline bool HashMap<T, U, V, W, X>::remove(iterator it)
348 {
349     if (it.m_impl == m_impl.end())
350         return false;
351     m_impl.internalCheckTableConsistency();
352     m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
353     return true;
354 }
355
356 template<typename T, typename U, typename V, typename W, typename X>
357 inline bool HashMap<T, U, V, W, X>::remove(const KeyType& key)
358 {
359     return remove(find(key));
360 }
361
362 template<typename T, typename U, typename V, typename W, typename X>
363 inline void HashMap<T, U, V, W, X>::clear()
364 {
365     m_impl.clear();
366 }
367
368 template<typename T, typename U, typename V, typename W, typename MappedTraits>
369 auto HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key) -> MappedType
370 {
371     iterator it = find(key);
372     if (it == end())
373         return MappedTraits::emptyValue();
374     MappedType value = WTF::move(it->value);
375     remove(it);
376     return value;
377 }
378
379 template<typename T, typename U, typename V, typename W, typename X>
380 inline void HashMap<T, U, V, W, X>::checkConsistency() const
381 {
382     m_impl.checkTableConsistency();
383 }
384
385 template<typename T, typename U, typename V, typename W, typename X>
386 inline bool HashMap<T, U, V, W, X>::isValidKey(const KeyType& key)
387 {
388     if (KeyTraits::isDeletedValue(key))
389         return false;
390
391     if (HashFunctions::safeToCompareToEmptyOrDeleted) {
392         if (key == KeyTraits::emptyValue())
393             return false;
394     } else {
395         if (isHashTraitsEmptyValue<KeyTraits>(key))
396             return false;
397     }
398
399     return true;
400 }
401
402 template<typename T, typename U, typename V, typename W, typename X>
403 bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
404 {
405     if (a.size() != b.size())
406         return false;
407
408     typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator;
409
410     const_iterator end = a.end();
411     const_iterator notFound = b.end();
412     for (const_iterator it = a.begin(); it != end; ++it) {
413         const_iterator bPos = b.find(it->key);
414         if (bPos == notFound || it->value != bPos->value)
415             return false;
416     }
417
418     return true;
419 }
420
421 template<typename T, typename U, typename V, typename W, typename X>
422 inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
423 {
424     return !(a == b);
425 }
426
427 template<typename T, typename U, typename V, typename W, typename X, typename Y>
428 inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
429 {
430     typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator;
431     
432     vector.resize(collection.size());
433     
434     iterator it = collection.begin().keys();
435     iterator end = collection.end().keys();
436     for (unsigned i = 0; it != end; ++it, ++i)
437         vector[i] = *it;
438 }  
439
440 template<typename T, typename U, typename V, typename W, typename X, typename Y>
441 inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
442 {
443     typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator;
444     
445     vector.resize(collection.size());
446     
447     iterator it = collection.begin().values();
448     iterator end = collection.end().values();
449     for (unsigned i = 0; it != end; ++it, ++i)
450         vector[i] = *it;
451 }   
452
453 } // namespace WTF
454
455 using WTF::HashMap;
456
457 #include <wtf/RefPtrHashMap.h>
458
459 #endif /* WTF_HashMap_h */