OLD | NEW |
1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
3 * | 3 // found in the LICENSE file. |
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 | 4 |
21 #ifndef WTF_HashSet_h | 5 #include "platform/wtf/HashSet.h" |
22 #define WTF_HashSet_h | |
23 | 6 |
24 #include "wtf/HashTable.h" | 7 // The contents of this header was moved to platform/wtf as part of |
25 #include "wtf/allocator/PartitionAllocator.h" | 8 // WTF migration project. See the following post for details: |
26 #include <initializer_list> | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
27 | |
28 namespace WTF { | |
29 | |
30 struct IdentityExtractor; | |
31 | |
32 // Note: empty or deleted values are not allowed, using them may lead to | |
33 // undefined behavior. For pointer valuess this means that null pointers are | |
34 // not allowed unless you supply custom traits. | |
35 template <typename ValueArg, | |
36 typename HashArg = typename DefaultHash<ValueArg>::Hash, | |
37 typename TraitsArg = HashTraits<ValueArg>, | |
38 typename Allocator = PartitionAllocator> | |
39 class HashSet { | |
40 USE_ALLOCATOR(HashSet, Allocator); | |
41 | |
42 private: | |
43 typedef HashArg HashFunctions; | |
44 typedef TraitsArg ValueTraits; | |
45 typedef typename ValueTraits::PeekInType ValuePeekInType; | |
46 | |
47 public: | |
48 typedef typename ValueTraits::TraitType ValueType; | |
49 using value_type = ValueType; | |
50 | |
51 private: | |
52 typedef HashTable<ValueType, | |
53 ValueType, | |
54 IdentityExtractor, | |
55 HashFunctions, | |
56 ValueTraits, | |
57 ValueTraits, | |
58 Allocator> | |
59 HashTableType; | |
60 | |
61 public: | |
62 typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> iterator; | |
63 typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> | |
64 const_iterator; | |
65 typedef typename HashTableType::AddResult AddResult; | |
66 | |
67 HashSet() { | |
68 static_assert(Allocator::isGarbageCollected || | |
69 !IsPointerToGarbageCollectedType<ValueArg>::value, | |
70 "Cannot put raw pointers to garbage-collected classes into " | |
71 "an off-heap HashSet. Use HeapHashSet<Member<T>> instead."); | |
72 } | |
73 HashSet(const HashSet&) = default; | |
74 HashSet& operator=(const HashSet&) = default; | |
75 HashSet(HashSet&&) = default; | |
76 HashSet& operator=(HashSet&&) = default; | |
77 | |
78 HashSet(std::initializer_list<ValueType> elements); | |
79 HashSet& operator=(std::initializer_list<ValueType> elements); | |
80 | |
81 void swap(HashSet& ref) { m_impl.swap(ref.m_impl); } | |
82 | |
83 unsigned size() const; | |
84 unsigned capacity() const; | |
85 bool isEmpty() const; | |
86 | |
87 void reserveCapacityForSize(unsigned size) { | |
88 m_impl.reserveCapacityForSize(size); | |
89 } | |
90 | |
91 iterator begin() const; | |
92 iterator end() const; | |
93 | |
94 iterator find(ValuePeekInType) const; | |
95 bool contains(ValuePeekInType) const; | |
96 | |
97 // An alternate version of find() that finds the object by hashing and | |
98 // comparing with some other type, to avoid the cost of type | |
99 // conversion. HashTranslator must have the following function members: | |
100 // static unsigned hash(const T&); | |
101 // static bool equal(const ValueType&, const T&); | |
102 template <typename HashTranslator, typename T> | |
103 iterator find(const T&) const; | |
104 template <typename HashTranslator, typename T> | |
105 bool contains(const T&) const; | |
106 | |
107 // The return value is a pair of an iterator to the new value's location, | |
108 // and a bool that is true if an new entry was added. | |
109 template <typename IncomingValueType> | |
110 AddResult insert(IncomingValueType&&); | |
111 | |
112 // An alternate version of add() that finds the object by hashing and | |
113 // comparing with some other type, to avoid the cost of type conversion if | |
114 // the object is already in the table. HashTranslator must have the | |
115 // following function members: | |
116 // static unsigned hash(const T&); | |
117 // static bool equal(const ValueType&, const T&); | |
118 // static translate(ValueType&, T&&, unsigned hashCode); | |
119 template <typename HashTranslator, typename T> | |
120 AddResult addWithTranslator(T&&); | |
121 | |
122 void erase(ValuePeekInType); | |
123 void erase(iterator); | |
124 void clear(); | |
125 template <typename Collection> | |
126 void removeAll(const Collection& toBeRemoved) { | |
127 WTF::removeAll(*this, toBeRemoved); | |
128 } | |
129 | |
130 ValueType take(iterator); | |
131 ValueType take(ValuePeekInType); | |
132 ValueType takeAny(); | |
133 | |
134 template <typename VisitorDispatcher> | |
135 void trace(VisitorDispatcher visitor) { | |
136 m_impl.trace(visitor); | |
137 } | |
138 | |
139 private: | |
140 HashTableType m_impl; | |
141 }; | |
142 | |
143 struct IdentityExtractor { | |
144 STATIC_ONLY(IdentityExtractor); | |
145 template <typename T> | |
146 static const T& extract(const T& t) { | |
147 return t; | |
148 } | |
149 }; | |
150 | |
151 template <typename Translator> | |
152 struct HashSetTranslatorAdapter { | |
153 STATIC_ONLY(HashSetTranslatorAdapter); | |
154 template <typename T> | |
155 static unsigned hash(const T& key) { | |
156 return Translator::hash(key); | |
157 } | |
158 template <typename T, typename U> | |
159 static bool equal(const T& a, const U& b) { | |
160 return Translator::equal(a, b); | |
161 } | |
162 template <typename T, typename U, typename V> | |
163 static void translate(T& location, U&& key, const V&, unsigned hashCode) { | |
164 Translator::translate(location, std::forward<U>(key), hashCode); | |
165 } | |
166 }; | |
167 | |
168 template <typename Value, | |
169 typename HashFunctions, | |
170 typename Traits, | |
171 typename Allocator> | |
172 HashSet<Value, HashFunctions, Traits, Allocator>::HashSet( | |
173 std::initializer_list<ValueType> elements) { | |
174 if (elements.size()) | |
175 m_impl.reserveCapacityForSize(elements.size()); | |
176 for (const ValueType& element : elements) | |
177 insert(element); | |
178 } | |
179 | |
180 template <typename Value, | |
181 typename HashFunctions, | |
182 typename Traits, | |
183 typename Allocator> | |
184 auto HashSet<Value, HashFunctions, Traits, Allocator>::operator=( | |
185 std::initializer_list<ValueType> elements) -> HashSet& { | |
186 *this = HashSet(std::move(elements)); | |
187 return *this; | |
188 } | |
189 | |
190 template <typename T, typename U, typename V, typename W> | |
191 inline unsigned HashSet<T, U, V, W>::size() const { | |
192 return m_impl.size(); | |
193 } | |
194 | |
195 template <typename T, typename U, typename V, typename W> | |
196 inline unsigned HashSet<T, U, V, W>::capacity() const { | |
197 return m_impl.capacity(); | |
198 } | |
199 | |
200 template <typename T, typename U, typename V, typename W> | |
201 inline bool HashSet<T, U, V, W>::isEmpty() const { | |
202 return m_impl.isEmpty(); | |
203 } | |
204 | |
205 template <typename T, typename U, typename V, typename W> | |
206 inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::begin() | |
207 const { | |
208 return m_impl.begin(); | |
209 } | |
210 | |
211 template <typename T, typename U, typename V, typename W> | |
212 inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::end() const { | |
213 return m_impl.end(); | |
214 } | |
215 | |
216 template <typename T, typename U, typename V, typename W> | |
217 inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::find( | |
218 ValuePeekInType value) const { | |
219 return m_impl.find(value); | |
220 } | |
221 | |
222 template <typename Value, | |
223 typename HashFunctions, | |
224 typename Traits, | |
225 typename Allocator> | |
226 inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains( | |
227 ValuePeekInType value) const { | |
228 return m_impl.contains(value); | |
229 } | |
230 | |
231 template <typename Value, | |
232 typename HashFunctions, | |
233 typename Traits, | |
234 typename Allocator> | |
235 template <typename HashTranslator, typename T> | |
236 typename HashSet<Value, HashFunctions, Traits, Allocator>:: | |
237 iterator inline HashSet<Value, HashFunctions, Traits, Allocator>::find( | |
238 const T& value) const { | |
239 return m_impl.template find<HashSetTranslatorAdapter<HashTranslator>>(value); | |
240 } | |
241 | |
242 template <typename Value, | |
243 typename HashFunctions, | |
244 typename Traits, | |
245 typename Allocator> | |
246 template <typename HashTranslator, typename T> | |
247 inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains( | |
248 const T& value) const { | |
249 return m_impl.template contains<HashSetTranslatorAdapter<HashTranslator>>( | |
250 value); | |
251 } | |
252 | |
253 template <typename T, typename U, typename V, typename W> | |
254 template <typename IncomingValueType> | |
255 inline typename HashSet<T, U, V, W>::AddResult HashSet<T, U, V, W>::insert( | |
256 IncomingValueType&& value) { | |
257 return m_impl.add(std::forward<IncomingValueType>(value)); | |
258 } | |
259 | |
260 template <typename Value, | |
261 typename HashFunctions, | |
262 typename Traits, | |
263 typename Allocator> | |
264 template <typename HashTranslator, typename T> | |
265 inline typename HashSet<Value, HashFunctions, Traits, Allocator>::AddResult | |
266 HashSet<Value, HashFunctions, Traits, Allocator>::addWithTranslator(T&& value) { | |
267 // Forward only the first argument, because the second argument isn't actually | |
268 // used in HashSetTranslatorAdapter. | |
269 return m_impl | |
270 .template addPassingHashCode<HashSetTranslatorAdapter<HashTranslator>>( | |
271 std::forward<T>(value), value); | |
272 } | |
273 | |
274 template <typename T, typename U, typename V, typename W> | |
275 inline void HashSet<T, U, V, W>::erase(iterator it) { | |
276 m_impl.remove(it.m_impl); | |
277 } | |
278 | |
279 template <typename T, typename U, typename V, typename W> | |
280 inline void HashSet<T, U, V, W>::erase(ValuePeekInType value) { | |
281 erase(find(value)); | |
282 } | |
283 | |
284 template <typename T, typename U, typename V, typename W> | |
285 inline void HashSet<T, U, V, W>::clear() { | |
286 m_impl.clear(); | |
287 } | |
288 | |
289 template <typename T, typename U, typename V, typename W> | |
290 inline auto HashSet<T, U, V, W>::take(iterator it) -> ValueType { | |
291 if (it == end()) | |
292 return ValueTraits::emptyValue(); | |
293 | |
294 ValueType result = std::move(const_cast<ValueType&>(*it)); | |
295 erase(it); | |
296 | |
297 return result; | |
298 } | |
299 | |
300 template <typename T, typename U, typename V, typename W> | |
301 inline auto HashSet<T, U, V, W>::take(ValuePeekInType value) -> ValueType { | |
302 return take(find(value)); | |
303 } | |
304 | |
305 template <typename T, typename U, typename V, typename W> | |
306 inline auto HashSet<T, U, V, W>::takeAny() -> ValueType { | |
307 return take(begin()); | |
308 } | |
309 | |
310 template <typename C, typename W> | |
311 inline void copyToVector(const C& collection, W& vector) { | |
312 typedef typename C::const_iterator iterator; | |
313 | |
314 { | |
315 // Disallow GC across resize allocation, see crbug.com/568173 | |
316 typename W::GCForbiddenScope scope; | |
317 vector.resize(collection.size()); | |
318 } | |
319 | |
320 iterator it = collection.begin(); | |
321 iterator end = collection.end(); | |
322 for (unsigned i = 0; it != end; ++it, ++i) | |
323 vector[i] = *it; | |
324 } | |
325 | |
326 } // namespace WTF | |
327 | |
328 using WTF::HashSet; | |
329 | |
330 #endif // WTF_HashSet_h | |
OLD | NEW |