• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2011 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_HashSet_h
22 #define WTF_HashSet_h
23 
24 #include "wtf/DefaultAllocator.h"
25 #include "wtf/HashTable.h"
26 
27 namespace WTF {
28 
29     struct IdentityExtractor;
30 
31     // Note: empty or deleted values are not allowed, using them may lead to undefined behavior.
32     // For pointer valuess this means that null pointers are not allowed unless you supply custom traits.
33     template<
34         typename ValueArg,
35         typename HashArg = typename DefaultHash<ValueArg>::Hash,
36         typename TraitsArg = HashTraits<ValueArg>,
37         typename Allocator = DefaultAllocator> class HashSet {
38         WTF_USE_ALLOCATOR(HashSet, Allocator);
39     private:
40         typedef HashArg HashFunctions;
41         typedef TraitsArg ValueTraits;
42         typedef typename ValueTraits::PeekInType ValuePeekInType;
43         typedef typename ValueTraits::PassInType ValuePassInType;
44         typedef typename ValueTraits::PassOutType ValuePassOutType;
45 
46     public:
47         typedef typename ValueTraits::TraitType ValueType;
48 
49     private:
50         typedef HashTable<ValueType, ValueType, IdentityExtractor,
51             HashFunctions, ValueTraits, ValueTraits, Allocator> HashTableType;
52 
53     public:
54         typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> iterator;
55         typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> const_iterator;
56         typedef typename HashTableType::AddResult AddResult;
57 
swap(HashSet & ref)58         void swap(HashSet& ref)
59         {
60             m_impl.swap(ref.m_impl);
61         }
62 
swap(typename Allocator::template OtherType<HashSet>::Type other)63         void swap(typename Allocator::template OtherType<HashSet>::Type other)
64         {
65             HashSet& ref = Allocator::getOther(other);
66             m_impl.swap(ref.m_impl);
67         }
68 
69         unsigned size() const;
70         unsigned capacity() const;
71         bool isEmpty() const;
72 
73         iterator begin() const;
74         iterator end() const;
75 
76         iterator find(ValuePeekInType) const;
77         bool contains(ValuePeekInType) const;
78 
79         // An alternate version of find() that finds the object by hashing and comparing
80         // with some other type, to avoid the cost of type conversion. HashTranslator
81         // must have the following function members:
82         //   static unsigned hash(const T&);
83         //   static bool equal(const ValueType&, const T&);
84         template<typename HashTranslator, typename T> iterator find(const T&) const;
85         template<typename HashTranslator, typename T> bool contains(const T&) const;
86 
87         // The return value is a pair of an iterator to the new value's location,
88         // and a bool that is true if an new entry was added.
89         AddResult add(ValuePassInType);
90 
91         // An alternate version of add() that finds the object by hashing and comparing
92         // with some other type, to avoid the cost of type conversion if the object is already
93         // in the table. HashTranslator must have the following function members:
94         //   static unsigned hash(const T&);
95         //   static bool equal(const ValueType&, const T&);
96         //   static translate(ValueType&, const T&, unsigned hashCode);
97         template<typename HashTranslator, typename T> AddResult add(const T&);
98 
99         void remove(ValuePeekInType);
100         void remove(iterator);
101         void clear();
102         template<typename Collection>
removeAll(const Collection & toBeRemoved)103         void removeAll(const Collection& toBeRemoved) { WTF::removeAll(*this, toBeRemoved); }
104 
105         static bool isValidValue(ValuePeekInType);
106 
107         ValuePassOutType take(iterator);
108         ValuePassOutType take(ValuePeekInType);
109         ValuePassOutType takeAny();
110 
trace(typename Allocator::Visitor * visitor)111         void trace(typename Allocator::Visitor* visitor) { m_impl.trace(visitor); }
112 
113     private:
114         HashTableType m_impl;
115     };
116 
117     struct IdentityExtractor {
118         template<typename T>
extractIdentityExtractor119         static const T& extract(const T& t) { return t; }
120     };
121 
122     template<typename Translator>
123     struct HashSetTranslatorAdapter {
hashHashSetTranslatorAdapter124         template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
equalHashSetTranslatorAdapter125         template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
translateHashSetTranslatorAdapter126         template<typename T, typename U> static void translate(T& location, const U& key, const U&, unsigned hashCode)
127         {
128             Translator::translate(location, key, hashCode);
129         }
130     };
131 
132     template<typename T, typename U, typename V, typename W>
size()133     inline unsigned HashSet<T, U, V, W>::size() const
134     {
135         return m_impl.size();
136     }
137 
138     template<typename T, typename U, typename V, typename W>
capacity()139     inline unsigned HashSet<T, U, V, W>::capacity() const
140     {
141         return m_impl.capacity();
142     }
143 
144     template<typename T, typename U, typename V, typename W>
isEmpty()145     inline bool HashSet<T, U, V, W>::isEmpty() const
146     {
147         return m_impl.isEmpty();
148     }
149 
150     template<typename T, typename U, typename V, typename W>
begin()151     inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::begin() const
152     {
153         return m_impl.begin();
154     }
155 
156     template<typename T, typename U, typename V, typename W>
end()157     inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::end() const
158     {
159         return m_impl.end();
160     }
161 
162     template<typename T, typename U, typename V, typename W>
find(ValuePeekInType value)163     inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::find(ValuePeekInType value) const
164     {
165         return m_impl.find(value);
166     }
167 
168     template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
contains(ValuePeekInType value)169     inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains(ValuePeekInType value) const
170     {
171         return m_impl.contains(value);
172     }
173 
174     template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
175     template<typename HashTranslator, typename T>
176     typename HashSet<Value, HashFunctions, Traits, Allocator>::iterator
find(const T & value)177     inline HashSet<Value, HashFunctions, Traits, Allocator>::find(const T& value) const
178     {
179         return m_impl.template find<HashSetTranslatorAdapter<HashTranslator> >(value);
180     }
181 
182     template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
183     template<typename HashTranslator, typename T>
contains(const T & value)184     inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains(const T& value) const
185     {
186         return m_impl.template contains<HashSetTranslatorAdapter<HashTranslator> >(value);
187     }
188 
189     template<typename T, typename U, typename V, typename W>
add(ValuePassInType value)190     inline typename HashSet<T, U, V, W>::AddResult HashSet<T, U, V, W>::add(ValuePassInType value)
191     {
192         return m_impl.add(value);
193     }
194 
195     template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
196     template<typename HashTranslator, typename T>
197     inline typename HashSet<Value, HashFunctions, Traits, Allocator>::AddResult
add(const T & value)198     HashSet<Value, HashFunctions, Traits, Allocator>::add(const T& value)
199     {
200         return m_impl.template addPassingHashCode<HashSetTranslatorAdapter<HashTranslator> >(value, value);
201     }
202 
203     template<typename T, typename U, typename V, typename W>
remove(iterator it)204     inline void HashSet<T, U, V, W>::remove(iterator it)
205     {
206         m_impl.remove(it.m_impl);
207     }
208 
209     template<typename T, typename U, typename V, typename W>
remove(ValuePeekInType value)210     inline void HashSet<T, U, V, W>::remove(ValuePeekInType value)
211     {
212         remove(find(value));
213     }
214 
215     template<typename T, typename U, typename V, typename W>
clear()216     inline void HashSet<T, U, V, W>::clear()
217     {
218         m_impl.clear();
219     }
220 
221     template<typename T, typename U, typename V, typename W>
isValidValue(ValuePeekInType value)222     inline bool HashSet<T, U, V, W>::isValidValue(ValuePeekInType value)
223     {
224         if (ValueTraits::isDeletedValue(value))
225             return false;
226 
227         if (HashFunctions::safeToCompareToEmptyOrDeleted) {
228             if (value == ValueTraits::emptyValue())
229                 return false;
230         } else {
231             if (isHashTraitsEmptyValue<ValueTraits>(value))
232                 return false;
233         }
234 
235         return true;
236     }
237 
238     template<typename T, typename U, typename V, typename W>
take(iterator it)239     inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::take(iterator it)
240     {
241         if (it == end())
242             return ValueTraits::emptyValue();
243 
244         ValuePassOutType result = ValueTraits::passOut(const_cast<ValueType&>(*it));
245         remove(it);
246 
247         return result;
248     }
249 
250     template<typename T, typename U, typename V, typename W>
take(ValuePeekInType value)251     inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::take(ValuePeekInType value)
252     {
253         return take(find(value));
254     }
255 
256     template<typename T, typename U, typename V, typename W>
takeAny()257     inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::takeAny()
258     {
259         return take(begin());
260     }
261 
262     template<typename C, typename W>
copyToVector(const C & collection,W & vector)263     inline void copyToVector(const C& collection, W& vector)
264     {
265         typedef typename C::const_iterator iterator;
266 
267         vector.resize(collection.size());
268 
269         iterator it = collection.begin();
270         iterator end = collection.end();
271         for (unsigned i = 0; it != end; ++it, ++i)
272             vector[i] = *it;
273     }
274 
275 } // namespace WTF
276 
277 using WTF::HashSet;
278 
279 #endif /* WTF_HashSet_h */
280