Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: Source/wtf/LinkedHashSet.h

Issue 223373002: Create HeapLinkedHashSet and LinkedHashSet, ordered heap-friendly hash sets. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Review feedback and many more tests Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/wtf/HashTable.h ('k') | Source/wtf/ListHashSetTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #ifndef WTF_LinkedHashSet_h
23 #define WTF_LinkedHashSet_h
24
25 #include "wtf/DefaultAllocator.h"
26 #include "wtf/HashSet.h"
27 #include "wtf/OwnPtr.h"
28 #include "wtf/PassOwnPtr.h"
29
30 namespace WTF {
31
32 // LinkedHashSet: Just like HashSet, this class provides a Set
33 // interface - a collection of unique objects with O(1) insertion,
34 // removal and test for containership. However, it also has an
35 // order - iterating it will always give back values in the order
36 // in which they are added.
37
38 // Unlike ListHashSet, but like most WTF collections, iteration is NOT safe
39 // against mutation of the LinkedHashSet.
40
41 template<typename Value, typename HashFunctions, typename HashTraits, typename A llocator> class LinkedHashSet;
42
43 template<typename LinkedHashSet> class LinkedHashSetIterator;
44 template<typename LinkedHashSet> class LinkedHashSetConstIterator;
45 template<typename LinkedHashSet> class LinkedHashSetReverseIterator;
46 template<typename LinkedHashSet> class LinkedHashSetConstReverseIterator;
47
48 template<typename Value, typename HashFunctions> struct LinkedHashSetTranslator;
49 template<typename Value> struct LinkedHashSetExtractor;
50 template<typename Value, typename ValueTraits> struct LinkedHashSetTraits;
51
52 class LinkedHashSetNodeBase {
53 public:
54 LinkedHashSetNodeBase() : m_prev(this), m_next(this) { }
55
56 void unlink()
57 {
58 if (!m_next)
59 return;
60 ASSERT(m_prev);
61 ASSERT(m_next->m_prev == this);
62 ASSERT(m_prev->m_next == this);
63 m_next->m_prev = m_prev;
64 m_prev->m_next = m_next;
65 }
66
67 ~LinkedHashSetNodeBase()
68 {
69 unlink();
70 }
71
72 void insertBefore(LinkedHashSetNodeBase& other)
73 {
74 other.m_next = this;
75 other.m_prev = m_prev;
76 m_prev->m_next = &other;
77 m_prev = &other;
78 ASSERT(other.m_next);
79 ASSERT(other.m_prev);
80 ASSERT(m_next);
81 ASSERT(m_prev);
82 }
83
84 void insertAfter(LinkedHashSetNodeBase& other)
85 {
86 other.m_prev = this;
87 other.m_next = m_next;
88 m_next->m_prev = &other;
89 m_next = &other;
90 ASSERT(other.m_next);
91 ASSERT(other.m_prev);
92 ASSERT(m_next);
93 ASSERT(m_prev);
94 }
95
96 LinkedHashSetNodeBase(LinkedHashSetNodeBase* prev, LinkedHashSetNodeBase* ne xt)
97 : m_prev(prev)
98 , m_next(next)
99 {
100 ASSERT((prev && next) || (!prev && !next));
101 }
102
103 LinkedHashSetNodeBase* m_prev;
104 LinkedHashSetNodeBase* m_next;
105
106 protected:
107 // If we take a copy of a node we can't copy the next and prev pointers,
108 // since they point to something that does not point at us. This is used
109 // inside the shouldExpand() "if" in HashTable::add.
110 LinkedHashSetNodeBase(const LinkedHashSetNodeBase& other)
111 : m_prev(0)
112 , m_next(0) { }
113
114 private:
115 // Should not be used.
116 LinkedHashSetNodeBase& operator=(const LinkedHashSetNodeBase& other);
117 };
118
119 template<typename ValueArg>
120 class LinkedHashSetNode : public LinkedHashSetNodeBase {
121 public:
122 LinkedHashSetNode(const ValueArg& value, LinkedHashSetNodeBase* prev, Linked HashSetNodeBase* next)
123 : LinkedHashSetNodeBase(prev, next)
124 , m_value(value)
125 {
126 }
127
128 ValueArg m_value;
129
130 private:
131 // Not used.
132 LinkedHashSetNode(const LinkedHashSetNode&);
Mikhail 2014/04/10 12:25:03 WTF_MAKE_NONCOPYABLE ?
Erik Corry 2014/04/10 13:47:29 Can't do that because it also overwrites the copy
133 };
134
135 template<
136 typename ValueArg,
137 typename HashFunctions = typename DefaultHash<ValueArg>::Hash,
138 typename TraitsArg = HashTraits<ValueArg>,
139 typename Allocator = DefaultAllocator>
140 class LinkedHashSet {
141 private:
142 typedef ValueArg Value;
143 typedef TraitsArg Traits;
144 typedef LinkedHashSetNode<Value> Node;
145 typedef LinkedHashSetNodeBase NodeBase;
146 typedef LinkedHashSetTranslator<Value, HashFunctions> NodeHashFunctions;
147 typedef LinkedHashSetTraits<Value, Traits> NodeHashTraits;
148
149 typedef HashTable<Node, Node, IdentityExtractor,
150 NodeHashFunctions, NodeHashTraits, NodeHashTraits, Allocator> ImplType;
151
152 public:
153 typedef LinkedHashSetIterator<LinkedHashSet> iterator;
154 friend class LinkedHashSetIterator<LinkedHashSet>;
155 typedef LinkedHashSetConstIterator<LinkedHashSet> const_iterator;
156 friend class LinkedHashSetConstIterator<LinkedHashSet>;
157
158 typedef LinkedHashSetReverseIterator<LinkedHashSet> reverse_iterator;
159 friend class LinkedHashSetReverseIterator<LinkedHashSet>;
160 typedef LinkedHashSetConstReverseIterator<LinkedHashSet> const_reverse_itera tor;
161 friend class LinkedHashSetConstReverseIterator<LinkedHashSet>;
162
163 struct AddResult {
164 AddResult(const typename ImplType::AddResult& hashTableAddResult)
165 : storedValue(&hashTableAddResult.storedValue->m_value)
166 , isNewEntry(hashTableAddResult.isNewEntry)
167 {
168 }
169
170 Value* storedValue;
171 bool isNewEntry;
172 };
173
174 typedef typename HashTraits<Value>::PeekInType ValuePeekInType;
175
176 void* operator new(size_t size)
Mads Ager (chromium) 2014/04/10 11:12:25 Did we now have a macro for this?
Erik Corry 2014/04/10 13:47:29 Done.
177 {
178 return Allocator::template malloc<void*, LinkedHashSet>(size);
179 }
180 void operator delete(void* p) { Allocator::free(p); }
181 void* operator new[](size_t size) { return Allocator::template newArray<Link edHashSet>(size); }
182 void operator delete[](void* p) { Allocator::deleteArray(p); }
183 void* operator new(size_t, NotNullTag, void* location)
184 {
185 COMPILE_ASSERT(!Allocator::isGarbageCollected, Garbage_collector_must_be _disabled);
186 ASSERT(location);
187 return location;
188 }
189
190 LinkedHashSet();
191 LinkedHashSet(const LinkedHashSet&);
192 LinkedHashSet& operator=(const LinkedHashSet&);
193 ~LinkedHashSet();
194
195 static void finalize(void* pointer) { reinterpret_cast<LinkedHashSet*>(point er)->~LinkedHashSet(); }
196
197 void swap(LinkedHashSet&);
198
199 unsigned size() const { return m_impl.size(); }
200 unsigned capacity() const { return m_impl.capacity(); }
201 bool isEmpty() const { return m_impl.isEmpty(); }
202
203 iterator begin() { return makeIterator(firstNode()); }
204 iterator end() { return makeIterator(anchor()); }
205 const_iterator begin() const { return makeConstIterator(firstNode()); }
206 const_iterator end() const { return makeConstIterator(anchor()); }
207
208 reverse_iterator rbegin() { return makeReverseIterator(lastNode()); }
209 reverse_iterator rend() { return makeReverseIterator(anchor()); }
210 const_reverse_iterator rbegin() const { return makeConstReverseIterator(last Node()); }
211 const_reverse_iterator rend() const { return makeConstReverseIterator(anchor ()); }
212
213 Value& first();
214 const Value& first() const;
215 void removeFirst();
216
217 Value& last();
218 const Value& last() const;
219 void removeLast();
220
221 iterator find(ValuePeekInType);
222 const_iterator find(ValuePeekInType) const;
223 bool contains(ValuePeekInType) const;
224
225 // An alternate version of find() that finds the object by hashing and compa ring
226 // with some other type, to avoid the cost of type conversion.
227 // The HashTranslator interface is defined in HashSet.
228 template<typename HashTranslator, typename T> iterator find(const T&);
229 template<typename HashTranslator, typename T> const_iterator find(const T&) const;
230 template<typename HashTranslator, typename T> bool contains(const T&) const;
231
232 // The return value of add is a pair of a pointer to the stored value,
233 // and a bool that is true if an new entry was added.
234 AddResult add(ValuePeekInType);
235
236 // Same as add() except that the return value is an
237 // iterator. Useful in cases where it's needed to have the
238 // same return value as find() and where it's not possible to
239 // use a pointer to the storedValue.
240 iterator addReturnIterator(ValuePeekInType);
241
242 // Add the value to the end of the collection. If the value was already in
243 // the list, it is moved to the end.
244 AddResult appendOrMoveToLast(ValuePeekInType);
245
246 // Add the value to the beginning of the collection. If the value was alread y in
247 // the list, it is moved to the beginning.
248 AddResult prependOrMoveToFirst(ValuePeekInType);
249
250 AddResult insertBefore(ValuePeekInType beforeValue, ValuePeekInType newValue );
251 AddResult insertBefore(iterator it, ValuePeekInType newValue) { return m_imp l.template add<NodeHashFunctions>(newValue, it.node()); }
252
253 void remove(ValuePeekInType);
254 void remove(iterator);
255 void clear() { m_impl.clear(); }
256
257 void trace(typename Allocator::Visitor* visitor) { m_impl.trace(visitor); }
258
259 int64_t modifications() const { return m_impl.modifications(); }
260 void checkModifications(int64_t mods) const { m_impl.checkModifications(mods ); }
Mikhail 2014/04/10 12:25:03 do we need those in release mode (or you think the
Erik Corry 2014/04/10 13:47:29 This one is only called from an assert. The one wi
261
262 private:
263 Node* anchor() { return reinterpret_cast<Node*>(&m_anchor); }
264 const Node* anchor() const { return reinterpret_cast<const Node*>(&m_anchor) ; }
265 Node* firstNode() { return reinterpret_cast<Node*>(m_anchor.m_next); }
266 const Node* firstNode() const { return reinterpret_cast<const Node*>(m_ancho r.m_next); }
267 Node* lastNode() { return reinterpret_cast<Node*>(m_anchor.m_prev); }
268 const Node* lastNode() const { return reinterpret_cast<const Node*>(m_anchor .m_prev); }
269
270 iterator makeIterator(const Node* position) { return iterator(position, this ); }
271 const_iterator makeConstIterator(const Node* position) const { return const_ iterator(position, this); }
272 reverse_iterator makeReverseIterator(const Node* position) { return reverse_ iterator(position, this); }
273 const_reverse_iterator makeConstReverseIterator(const Node* position) const { return const_reverse_iterator(position, this); }
274
275 ImplType m_impl;
276 NodeBase m_anchor;
277 #ifndef ASSERT_ENABLED
278 uint64_t m_modifications;
279 #endif
280 };
281
282 template<typename Value, typename HashFunctions>
283 struct LinkedHashSetTranslator {
284 typedef LinkedHashSetNode<Value> Node;
285 typedef LinkedHashSetNodeBase NodeBase;
286 typedef typename HashTraits<Value>::PeekInType ValuePeekInType;
287 static unsigned hash(const Node& node) { return HashFunctions::hash(node.m_v alue); }
288 static unsigned hash(const ValuePeekInType& key) { return HashFunctions::has h(key); }
289 static bool equal(const Node& a, const ValuePeekInType& b) { return HashFunc tions::equal(a.m_value, b); }
290 static bool equal(const Node& a, const Node& b) { return HashFunctions::equa l(a.m_value, b.m_value); }
291 static void translate(Node& location, ValuePeekInType key, NodeBase* anchor)
292 {
293 location.m_value = key;
294 anchor->insertBefore(location);
295 }
296
297 // Empty (or deleted) slots have the m_next pointer set to null, but we
298 // don't do anything to the other fields, which may contain junk.
299 // Therefore you can't compare a newly constructed empty value with a
300 // slot and get the right answer.
301 static const bool safeToCompareToEmptyOrDeleted = false;
302 };
303
304 template<typename Value>
305 struct LinkedHashSetExtractor {
306 static const Value& extract(const LinkedHashSetNode<Value>& node) { return n ode.m_value; }
307 };
308
309 template<typename Value, typename ValueTraitsArg>
310 struct LinkedHashSetTraits : public SimpleClassHashTraits<LinkedHashSetNode<Valu e> > {
311 typedef LinkedHashSetNode<Value> Node;
312 typedef ValueTraitsArg ValueTraits;
313
314 // The slot is empty when the m_next field is zero so it's safe to zero
315 // the backing.
316 static const bool emptyValueIsZero = true;
317
318 static const bool hasIsEmptyValueFunction = true;
319 static bool isEmptyValue(const Node& value) { return !value.m_next; }
320
321 static const int deletedValue = -1;
322
323 static void constructDeletedValue(Node& slot) { slot.m_next = reinterpret_ca st<Node*>(deletedValue); }
324 static bool isDeletedValue(const Node& slot) { return slot.m_next == reinter pret_cast<Node*>(deletedValue); }
325
326 // We always need to call destructors, that's how we get linked and
327 // unlinked from the chain.
328 static const bool needsDestruction = true;
329
330 // Whether we need to trace and do weak processing depends on the traits of
331 // the type inside the node.
332 template<typename U = void>
333 struct NeedsTracingLazily {
334 static const bool value = ValueTraits::template NeedsTracingLazily<>::va lue;
335 };
336 static const bool isWeak = ValueTraits::isWeak;
337 };
338
339 template<typename LinkedHashSetType>
340 class LinkedHashSetIterator {
341 private:
342 typedef typename LinkedHashSetType::Node Node;
343 typedef typename LinkedHashSetType::Traits Traits;
344
345 typedef typename LinkedHashSetType::Value& ReferenceType;
346 typedef typename LinkedHashSetType::Value* PointerType;
347
348 typedef LinkedHashSetConstIterator<LinkedHashSetType> const_iterator;
349
350 Node* node() const { return const_cast<Node*>(m_iterator.node()); }
Mikhail 2014/04/10 12:25:03 looks like it should not be a const method
Erik Corry 2014/04/10 13:47:29 Done.
351
352 protected:
353 LinkedHashSetIterator(const Node* position, LinkedHashSetType* m_container)
354 : m_iterator(position , m_container)
355 {
356 }
357
358 public:
359 // Default copy, assignment and destructor are OK.
360
361 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
362 ReferenceType operator*() const { return *get(); }
363 PointerType operator->() const { return get(); }
364
365 LinkedHashSetIterator& operator++() { ++m_iterator; return *this; }
366 LinkedHashSetIterator& operator--() { --m_iterator; return *this; }
367
368 // Postfix ++ and -- intentionally omitted.
369
370 // Comparison.
371 bool operator==(const LinkedHashSetIterator& other) const { return m_iterato r == other.m_iterator; }
372 bool operator!=(const LinkedHashSetIterator& other) const { return m_iterato r != other.m_iterator; }
373
374 operator const_iterator() const { return m_iterator; }
375
376 protected:
377 const_iterator m_iterator;
378 template<typename T, typename U, typename V, typename W> friend class Linked HashSet;
379 };
380
381 template<typename LinkedHashSetType>
382 class LinkedHashSetConstIterator {
383 private:
384 typedef typename LinkedHashSetType::Node Node;
385 typedef typename LinkedHashSetType::Traits Traits;
386
387 typedef const typename LinkedHashSetType::Value& ReferenceType;
388 typedef const typename LinkedHashSetType::Value* PointerType;
389
390 const Node* node() const { return static_cast<const Node*>(m_position); }
391
392 protected:
393 LinkedHashSetConstIterator(const LinkedHashSetNodeBase* position, const Link edHashSetType* container)
394 : m_position(position)
395 #ifdef ASSERT_ENABLED
396 , m_container(container)
397 , m_containerModifications(container->modifications())
398 #endif
399 {
400 }
401
402 public:
403 PointerType get() const
404 {
405 checkModifications();
406 return &static_cast<const Node*>(m_position)->m_value;
407 }
408 ReferenceType operator*() const { return *get(); }
409 PointerType operator->() const { return get(); }
410
411 LinkedHashSetConstIterator& operator++()
412 {
413 ASSERT(m_position);
414 checkModifications();
415 m_position = m_position->m_next;
416 return *this;
417 }
418
419 LinkedHashSetConstIterator& operator--()
420 {
421 ASSERT(m_position);
422 checkModifications();
423 m_position = m_position->m_prev;
424 return *this;
425 }
426
427 // Postfix ++ and -- intentionally omitted.
428
429 // Comparison.
430 bool operator==(const LinkedHashSetConstIterator& other) const
431 {
432 return m_position == other.m_position;
433 }
434 bool operator!=(const LinkedHashSetConstIterator& other) const
435 {
436 return m_position != other.m_position;
437 }
438
439 private:
440 const LinkedHashSetNodeBase* m_position;
441 #ifdef ASSERT_ENABLED
442 void checkModifications() const { m_container->checkModifications(m_containe rModifications); }
443 const LinkedHashSetType* m_container;
444 int64_t m_containerModifications;
445 #else
446 void checkModifications() const { }
447 #endif
448 template<typename T, typename U, typename V, typename W> friend class Linked HashSet;
449 friend class LinkedHashSetIterator<LinkedHashSetType>;
450 };
451
452 template<typename LinkedHashSetType>
453 class LinkedHashSetReverseIterator : public LinkedHashSetIterator<LinkedHashSetT ype> {
454 typedef LinkedHashSetIterator<LinkedHashSetType> Superclass;
455 typedef LinkedHashSetConstReverseIterator<LinkedHashSetType> const_reverse_i terator;
456 typedef typename LinkedHashSetType::Node Node;
457
458 protected:
459 LinkedHashSetReverseIterator(const Node* position, LinkedHashSetType* contai ner)
460 : Superclass(position, container) { }
461
462 public:
463 LinkedHashSetReverseIterator& operator++() { Superclass::operator--(); retur n *this; }
464 LinkedHashSetReverseIterator& operator--() { Superclass::operator++(); retur n *this; }
465
466 // Postfix ++ and -- intentionally omitted.
467
468 operator const_reverse_iterator() const { return *reinterpret_cast<const_rev erse_iterator*>(this); }
469
470 template<typename T, typename U, typename V, typename W> friend class Linked HashSet;
471 };
472
473 template<typename LinkedHashSetType>
474 class LinkedHashSetConstReverseIterator : public LinkedHashSetConstIterator<Link edHashSetType> {
475 typedef LinkedHashSetConstIterator<LinkedHashSetType> Superclass;
476 typedef typename LinkedHashSetType::Node Node;
477
478 public:
479 LinkedHashSetConstReverseIterator(const Node* position, const LinkedHashSetT ype* container)
480 : Superclass(position, container) { }
481
482 LinkedHashSetConstReverseIterator& operator++() { Superclass::operator--(); return *this; }
483 LinkedHashSetConstReverseIterator& operator--() { Superclass::operator++(); return *this; }
484
485 // Postfix ++ and -- intentionally omitted.
486
487 template<typename T, typename U, typename V, typename W> friend class Linked HashSet;
488 };
489
490 template<typename T, typename U, typename V, typename W>
491 inline LinkedHashSet<T, U, V, W>::LinkedHashSet() { }
492
493 template<typename T, typename U, typename V, typename W>
494 inline LinkedHashSet<T, U, V, W>::LinkedHashSet(const LinkedHashSet& other)
495 : m_anchor()
496 {
497 const_iterator end = other.end();
498 for (const_iterator it = other.begin(); it != end; ++it)
499 add(*it);
500 }
501
502 template<typename T, typename U, typename V, typename W>
503 inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=(const Lin kedHashSet& other)
504 {
505 LinkedHashSet tmp(other);
506 swap(tmp);
507 return *this;
508 }
509
510 template<typename T, typename U, typename V, typename W>
511 inline void LinkedHashSet<T, U, V, W>::swap(LinkedHashSet& other)
512 {
513 m_impl.swap(other.m_impl);
514 swap(m_anchor, other.m_anchor);
515 }
516
517 template<typename T, typename U, typename V, typename Allocator>
518 inline LinkedHashSet<T, U, V, Allocator>::~LinkedHashSet()
519 {
520 // The destructor of m_anchor will implicitly be called here, which will
521 // unlink the anchor from the collection.
522 }
523
524 template<typename T, typename U, typename V, typename W>
525 inline T& LinkedHashSet<T, U, V, W>::first()
526 {
527 ASSERT(!isEmpty());
528 return firstNode()->m_value;
529 }
530
531 template<typename T, typename U, typename V, typename W>
532 inline const T& LinkedHashSet<T, U, V, W>::first() const
533 {
534 ASSERT(!isEmpty());
535 return firstNode()->m_value;
536 }
537
538 template<typename T, typename U, typename V, typename W>
539 inline void LinkedHashSet<T, U, V, W>::removeFirst()
540 {
541 ASSERT(!isEmpty());
542 m_impl.remove(static_cast<Node*>(m_anchor.m_next));
543 }
544
545 template<typename T, typename U, typename V, typename W>
546 inline T& LinkedHashSet<T, U, V, W>::last()
547 {
548 ASSERT(!isEmpty());
549 return lastNode()->m_value;
550 }
551
552 template<typename T, typename U, typename V, typename W>
553 inline const T& LinkedHashSet<T, U, V, W>::last() const
554 {
555 ASSERT(!isEmpty());
556 return lastNode()->m_value;
557 }
558
559 template<typename T, typename U, typename V, typename W>
560 inline void LinkedHashSet<T, U, V, W>::removeLast()
561 {
562 ASSERT(!isEmpty());
563 m_impl.remove(static_cast<Node*>(m_anchor.m_prev));
564 }
565
566 template<typename T, typename U, typename V, typename W>
567 inline typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::f ind(ValuePeekInType value)
568 {
569 LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::NodeHashFu nctions, ValuePeekInType>(value);
570 if (!node)
571 return end();
572 return makeIterator(node);
573 }
574
575 template<typename T, typename U, typename V, typename W>
576 inline typename LinkedHashSet<T, U, V, W>::const_iterator LinkedHashSet<T, U, V, W>::find(ValuePeekInType value) const
577 {
578 const LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::Node HashFunctions, ValuePeekInType>(value);
579 if (!node)
580 return end();
581 return makeConstIterator(node);
582 }
583
584 template<typename Value, typename U, typename V, typename W>
585 template<typename HashTranslator, typename T>
586 inline typename LinkedHashSet<Value, U, V, W>::iterator LinkedHashSet<Value, U, V, W>::find(const T& value)
587 {
588 iterator it = begin();
589 iterator endIterator = end();
Erik Corry 2014/04/10 10:53:06 I need to fix this implementation to not loop.
Erik Corry 2014/04/10 13:47:29 Done.
590 while (it != endIterator && !HashTranslator::template equal<Value, T>(it->m_ value, value))
591 ++it;
592 return it;
593 }
594
595 template<typename Value, typename U, typename V, typename W>
596 template<typename HashTranslator, typename T>
597 inline typename LinkedHashSet<Value, U, V, W>::const_iterator LinkedHashSet<Valu e, U, V, W>::find(const T& value) const
598 {
599 const_iterator it = begin();
600 const_iterator endIterator = end();
601 while (it != endIterator && !HashTranslator::template equal<Value, T>(it->m_ value, value))
602 ++it;
603 return it;
604 }
605
606 template<typename Translator>
607 struct LinkedHashSetTranslatorAdapter {
608 template<typename T> static unsigned hash(const T& key) { return Translator: :hash(key); }
609 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); }
610 };
611
612 template<typename Value, typename U, typename V, typename W>
613 template<typename HashTranslator, typename T>
614 inline bool LinkedHashSet<Value, U, V, W>::contains(const T& value) const
615 {
616 return m_impl.template contains<LinkedHashSetTranslatorAdapter<HashTranslato r> >(value);
617 }
618
619 template<typename T, typename U, typename V, typename W>
620 inline bool LinkedHashSet<T, U, V, W>::contains(ValuePeekInType value) const
621 {
622 return m_impl.template contains<NodeHashFunctions>(value);
623 }
624
625 template<typename Value, typename HashFunctions, typename Traits, typename Alloc ator>
626 typename LinkedHashSet<Value, HashFunctions, Traits, Allocator>::AddResult Linke dHashSet<Value, HashFunctions, Traits, Allocator>::add(ValuePeekInType value)
627 {
628 return m_impl.template add<NodeHashFunctions>(value, &m_anchor);
629 }
630
631 template<typename T, typename U, typename V, typename W>
632 typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::addRetur nIterator(ValuePeekInType value)
633 {
634 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions> (value, &m_anchor);
635 return makeIterator(result.storedValue);
636 }
637
638 template<typename T, typename U, typename V, typename W>
639 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::appendO rMoveToLast(ValuePeekInType value)
640 {
641 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions> (value, &m_anchor);
642 Node* node = result.storedValue;
643 if (!result.isNewEntry) {
644 node->unlink();
645 m_anchor.insertBefore(*node);
646 }
647 return result;
648 }
649
650 template<typename T, typename U, typename V, typename W>
651 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::prepend OrMoveToFirst(ValuePeekInType value)
652 {
653 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions> (value, m_anchor.m_next);
654 Node* node = result.storedValue;
655 if (!result.isNewEntry) {
656 node->unlink();
657 m_anchor.insertAfter(*node);
658 }
659 return result;
660 }
661
662 template<typename T, typename U, typename V, typename W>
663 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::insertB efore(ValuePeekInType beforeValue, ValuePeekInType newValue)
664 {
665 return insertBefore(find(beforeValue), newValue);
666 }
667
668 template<typename T, typename U, typename V, typename W>
669 inline void LinkedHashSet<T, U, V, W>::remove(iterator it)
670 {
671 if (it == end())
672 return;
673 m_impl.remove(it.node());
674 }
675
676 template<typename T, typename U, typename V, typename W>
677 inline void LinkedHashSet<T, U, V, W>::remove(ValuePeekInType value)
678 {
679 remove(find(value));
680 }
681
682 template<typename T>
683 struct IsWeak<LinkedHashSetNode<T> > {
684 static const bool value = IsWeak<T>::value;
685 };
686
687 inline void swap(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b)
688 {
689 typedef LinkedHashSetNodeBase Base;
690 swap(a.m_next, b.m_next);
691 swap(a.m_prev, b.m_prev);
692 if (b.m_next) {
693 b.m_next->m_prev = &b;
694 b.m_prev->m_next = &b;
695 }
696 if (a.m_next) {
697 a.m_next->m_prev = &a;
698 a.m_prev->m_next = &a;
699 }
700 }
701
702 template<typename T>
703 inline void swap(LinkedHashSetNode<T>& a, LinkedHashSetNode<T>& b)
704 {
705 typedef LinkedHashSetNodeBase Base;
706
707 swap(static_cast<Base&>(a), static_cast<Base&>(b));
708
709 using namespace std;
Mads Ager (chromium) 2014/04/10 11:12:25 I thought we were not doing this?
Erik Corry 2014/04/10 13:47:29 I was a bit confused too, but the check-webkit-sty
Erik Corry 2014/04/10 13:53:07 Or I could just remove the using directive complet
710 swap(a.m_value, b.m_value);
711 }
712
713 }
714
715 using WTF::LinkedHashSet;
716
717 #endif /* WTF_LinkedHashSet_h */
OLDNEW
« no previous file with comments | « Source/wtf/HashTable.h ('k') | Source/wtf/ListHashSetTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698