2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com>
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.
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.
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.
22 #ifndef WTF_LinkedHashSet_h
23 #define WTF_LinkedHashSet_h
25 #include "wtf/DefaultAllocator.h"
26 #include "wtf/HashSet.h"
27 #include "wtf/OwnPtr.h"
28 #include "wtf/PassOwnPtr.h"
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.
38 // Unlike ListHashSet, but like most WTF collections, iteration is NOT safe
39 // against mutation of the LinkedHashSet.
41 template<typename Value, typename HashFunctions, typename HashTraits, typename Allocator> class LinkedHashSet;
43 template<typename LinkedHashSet> class LinkedHashSetIterator;
44 template<typename LinkedHashSet> class LinkedHashSetConstIterator;
45 template<typename LinkedHashSet> class LinkedHashSetReverseIterator;
46 template<typename LinkedHashSet> class LinkedHashSetConstReverseIterator;
48 template<typename Value, typename HashFunctions> struct LinkedHashSetTranslator;
49 template<typename Value> struct LinkedHashSetExtractor;
50 template<typename Value, typename ValueTraits> struct LinkedHashSetTraits;
52 class LinkedHashSetNodeBase {
54 LinkedHashSetNodeBase() : m_prev(this), m_next(this) { }
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;
67 ~LinkedHashSetNodeBase()
72 void insertBefore(LinkedHashSetNodeBase& other)
75 other.m_prev = m_prev;
76 m_prev->m_next = &other;
84 void insertAfter(LinkedHashSetNodeBase& other)
87 other.m_next = m_next;
88 m_next->m_prev = &other;
96 LinkedHashSetNodeBase(LinkedHashSetNodeBase* prev, LinkedHashSetNodeBase* next)
100 ASSERT((prev && next) || (!prev && !next));
103 LinkedHashSetNodeBase* m_prev;
104 LinkedHashSetNodeBase* m_next;
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)
115 // Should not be used.
116 LinkedHashSetNodeBase& operator=(const LinkedHashSetNodeBase& other);
119 template<typename ValueArg>
120 class LinkedHashSetNode : public LinkedHashSetNodeBase {
122 LinkedHashSetNode(const ValueArg& value, LinkedHashSetNodeBase* prev, LinkedHashSetNodeBase* next)
123 : LinkedHashSetNodeBase(prev, next)
132 LinkedHashSetNode(const LinkedHashSetNode&);
137 typename HashFunctions = typename DefaultHash<ValueArg>::Hash,
138 typename TraitsArg = HashTraits<ValueArg>,
139 typename Allocator = DefaultAllocator>
140 class LinkedHashSet {
141 WTF_USE_ALLOCATOR(LinkedHashSet, Allocator);
143 typedef ValueArg Value;
144 typedef TraitsArg Traits;
145 typedef LinkedHashSetNode<Value> Node;
146 typedef LinkedHashSetNodeBase NodeBase;
147 typedef LinkedHashSetTranslator<Value, HashFunctions> NodeHashFunctions;
148 typedef LinkedHashSetTraits<Value, Traits> NodeHashTraits;
150 typedef HashTable<Node, Node, IdentityExtractor,
151 NodeHashFunctions, NodeHashTraits, NodeHashTraits, Allocator> ImplType;
154 typedef LinkedHashSetIterator<LinkedHashSet> iterator;
155 friend class LinkedHashSetIterator<LinkedHashSet>;
156 typedef LinkedHashSetConstIterator<LinkedHashSet> const_iterator;
157 friend class LinkedHashSetConstIterator<LinkedHashSet>;
159 typedef LinkedHashSetReverseIterator<LinkedHashSet> reverse_iterator;
160 friend class LinkedHashSetReverseIterator<LinkedHashSet>;
161 typedef LinkedHashSetConstReverseIterator<LinkedHashSet> const_reverse_iterator;
162 friend class LinkedHashSetConstReverseIterator<LinkedHashSet>;
165 AddResult(const typename ImplType::AddResult& hashTableAddResult)
166 : storedValue(&hashTableAddResult.storedValue->m_value)
167 , isNewEntry(hashTableAddResult.isNewEntry)
175 typedef typename HashTraits<Value>::PeekInType ValuePeekInType;
178 LinkedHashSet(const LinkedHashSet&);
179 LinkedHashSet& operator=(const LinkedHashSet&);
181 // Needs finalization. The anchor needs to unlink itself from the chain.
184 static void finalize(void* pointer) { reinterpret_cast<LinkedHashSet*>(pointer)->~LinkedHashSet(); }
186 void swap(LinkedHashSet&);
188 unsigned size() const { return m_impl.size(); }
189 unsigned capacity() const { return m_impl.capacity(); }
190 bool isEmpty() const { return m_impl.isEmpty(); }
192 iterator begin() { return makeIterator(firstNode()); }
193 iterator end() { return makeIterator(anchor()); }
194 const_iterator begin() const { return makeConstIterator(firstNode()); }
195 const_iterator end() const { return makeConstIterator(anchor()); }
197 reverse_iterator rbegin() { return makeReverseIterator(lastNode()); }
198 reverse_iterator rend() { return makeReverseIterator(anchor()); }
199 const_reverse_iterator rbegin() const { return makeConstReverseIterator(lastNode()); }
200 const_reverse_iterator rend() const { return makeConstReverseIterator(anchor()); }
203 const Value& first() const;
207 const Value& last() const;
210 iterator find(ValuePeekInType);
211 const_iterator find(ValuePeekInType) const;
212 bool contains(ValuePeekInType) const;
214 // An alternate version of find() that finds the object by hashing and comparing
215 // with some other type, to avoid the cost of type conversion.
216 // The HashTranslator interface is defined in HashSet.
217 template<typename HashTranslator, typename T> iterator find(const T&);
218 template<typename HashTranslator, typename T> const_iterator find(const T&) const;
219 template<typename HashTranslator, typename T> bool contains(const T&) const;
221 // The return value of add is a pair of a pointer to the stored value,
222 // and a bool that is true if an new entry was added.
223 AddResult add(ValuePeekInType);
225 // Same as add() except that the return value is an
226 // iterator. Useful in cases where it's needed to have the
227 // same return value as find() and where it's not possible to
228 // use a pointer to the storedValue.
229 iterator addReturnIterator(ValuePeekInType);
231 // Add the value to the end of the collection. If the value was already in
232 // the list, it is moved to the end.
233 AddResult appendOrMoveToLast(ValuePeekInType);
235 // Add the value to the beginning of the collection. If the value was already in
236 // the list, it is moved to the beginning.
237 AddResult prependOrMoveToFirst(ValuePeekInType);
239 AddResult insertBefore(ValuePeekInType beforeValue, ValuePeekInType newValue);
240 AddResult insertBefore(iterator it, ValuePeekInType newValue) { return m_impl.template add<NodeHashFunctions>(newValue, it.node()); }
242 void remove(ValuePeekInType);
243 void remove(iterator);
244 void clear() { m_impl.clear(); }
245 template<typename Collection>
246 void removeAll(const Collection& other) { WTF::removeAll(*this, other); }
248 void trace(typename Allocator::Visitor* visitor) { m_impl.trace(visitor); }
250 int64_t modifications() const { return m_impl.modifications(); }
251 void checkModifications(int64_t mods) const { m_impl.checkModifications(mods); }
254 Node* anchor() { return reinterpret_cast<Node*>(&m_anchor); }
255 const Node* anchor() const { return reinterpret_cast<const Node*>(&m_anchor); }
256 Node* firstNode() { return reinterpret_cast<Node*>(m_anchor.m_next); }
257 const Node* firstNode() const { return reinterpret_cast<const Node*>(m_anchor.m_next); }
258 Node* lastNode() { return reinterpret_cast<Node*>(m_anchor.m_prev); }
259 const Node* lastNode() const { return reinterpret_cast<const Node*>(m_anchor.m_prev); }
261 iterator makeIterator(const Node* position) { return iterator(position, this); }
262 const_iterator makeConstIterator(const Node* position) const { return const_iterator(position, this); }
263 reverse_iterator makeReverseIterator(const Node* position) { return reverse_iterator(position, this); }
264 const_reverse_iterator makeConstReverseIterator(const Node* position) const { return const_reverse_iterator(position, this); }
268 #ifndef ASSERT_ENABLED
269 uint64_t m_modifications;
273 template<typename Value, typename HashFunctions>
274 struct LinkedHashSetTranslator {
275 typedef LinkedHashSetNode<Value> Node;
276 typedef LinkedHashSetNodeBase NodeBase;
277 typedef typename HashTraits<Value>::PeekInType ValuePeekInType;
278 static unsigned hash(const Node& node) { return HashFunctions::hash(node.m_value); }
279 static unsigned hash(const ValuePeekInType& key) { return HashFunctions::hash(key); }
280 static bool equal(const Node& a, const ValuePeekInType& b) { return HashFunctions::equal(a.m_value, b); }
281 static bool equal(const Node& a, const Node& b) { return HashFunctions::equal(a.m_value, b.m_value); }
282 static void translate(Node& location, ValuePeekInType key, NodeBase* anchor)
284 location.m_value = key;
285 anchor->insertBefore(location);
288 // Empty (or deleted) slots have the m_next pointer set to null, but we
289 // don't do anything to the other fields, which may contain junk.
290 // Therefore you can't compare a newly constructed empty value with a
291 // slot and get the right answer.
292 static const bool safeToCompareToEmptyOrDeleted = false;
295 template<typename Value>
296 struct LinkedHashSetExtractor {
297 static const Value& extract(const LinkedHashSetNode<Value>& node) { return node.m_value; }
300 template<typename Value, typename ValueTraitsArg>
301 struct LinkedHashSetTraits : public SimpleClassHashTraits<LinkedHashSetNode<Value> > {
302 typedef LinkedHashSetNode<Value> Node;
303 typedef ValueTraitsArg ValueTraits;
305 // The slot is empty when the m_next field is zero so it's safe to zero
307 static const bool emptyValueIsZero = true;
309 static const bool hasIsEmptyValueFunction = true;
310 static bool isEmptyValue(const Node& value) { return !value.m_next; }
312 static const int deletedValue = -1;
314 static void constructDeletedValue(Node& slot) { slot.m_next = reinterpret_cast<Node*>(deletedValue); }
315 static bool isDeletedValue(const Node& slot) { return slot.m_next == reinterpret_cast<Node*>(deletedValue); }
317 // We always need to call destructors, that's how we get linked and
318 // unlinked from the chain.
319 static const bool needsDestruction = true;
321 // Whether we need to trace and do weak processing depends on the traits of
322 // the type inside the node.
323 template<typename U = void>
324 struct NeedsTracingLazily {
325 static const bool value = ValueTraits::template NeedsTracingLazily<>::value;
327 static const bool isWeak = ValueTraits::isWeak;
330 template<typename LinkedHashSetType>
331 class LinkedHashSetIterator {
333 typedef typename LinkedHashSetType::Node Node;
334 typedef typename LinkedHashSetType::Traits Traits;
336 typedef typename LinkedHashSetType::Value& ReferenceType;
337 typedef typename LinkedHashSetType::Value* PointerType;
339 typedef LinkedHashSetConstIterator<LinkedHashSetType> const_iterator;
341 Node* node() { return const_cast<Node*>(m_iterator.node()); }
344 LinkedHashSetIterator(const Node* position, LinkedHashSetType* m_container)
345 : m_iterator(position , m_container)
350 // Default copy, assignment and destructor are OK.
352 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
353 ReferenceType operator*() const { return *get(); }
354 PointerType operator->() const { return get(); }
356 LinkedHashSetIterator& operator++() { ++m_iterator; return *this; }
357 LinkedHashSetIterator& operator--() { --m_iterator; return *this; }
359 // Postfix ++ and -- intentionally omitted.
362 bool operator==(const LinkedHashSetIterator& other) const { return m_iterator == other.m_iterator; }
363 bool operator!=(const LinkedHashSetIterator& other) const { return m_iterator != other.m_iterator; }
365 operator const_iterator() const { return m_iterator; }
368 const_iterator m_iterator;
369 template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
372 template<typename LinkedHashSetType>
373 class LinkedHashSetConstIterator {
375 typedef typename LinkedHashSetType::Node Node;
376 typedef typename LinkedHashSetType::Traits Traits;
378 typedef const typename LinkedHashSetType::Value& ReferenceType;
379 typedef const typename LinkedHashSetType::Value* PointerType;
381 const Node* node() const { return static_cast<const Node*>(m_position); }
384 LinkedHashSetConstIterator(const LinkedHashSetNodeBase* position, const LinkedHashSetType* container)
385 : m_position(position)
386 #ifdef ASSERT_ENABLED
387 , m_container(container)
388 , m_containerModifications(container->modifications())
394 PointerType get() const
396 checkModifications();
397 return &static_cast<const Node*>(m_position)->m_value;
399 ReferenceType operator*() const { return *get(); }
400 PointerType operator->() const { return get(); }
402 LinkedHashSetConstIterator& operator++()
405 checkModifications();
406 m_position = m_position->m_next;
410 LinkedHashSetConstIterator& operator--()
413 checkModifications();
414 m_position = m_position->m_prev;
418 // Postfix ++ and -- intentionally omitted.
421 bool operator==(const LinkedHashSetConstIterator& other) const
423 return m_position == other.m_position;
425 bool operator!=(const LinkedHashSetConstIterator& other) const
427 return m_position != other.m_position;
431 const LinkedHashSetNodeBase* m_position;
432 #ifdef ASSERT_ENABLED
433 void checkModifications() const { m_container->checkModifications(m_containerModifications); }
434 const LinkedHashSetType* m_container;
435 int64_t m_containerModifications;
437 void checkModifications() const { }
439 template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
440 friend class LinkedHashSetIterator<LinkedHashSetType>;
443 template<typename LinkedHashSetType>
444 class LinkedHashSetReverseIterator : public LinkedHashSetIterator<LinkedHashSetType> {
445 typedef LinkedHashSetIterator<LinkedHashSetType> Superclass;
446 typedef LinkedHashSetConstReverseIterator<LinkedHashSetType> const_reverse_iterator;
447 typedef typename LinkedHashSetType::Node Node;
450 LinkedHashSetReverseIterator(const Node* position, LinkedHashSetType* container)
451 : Superclass(position, container) { }
454 LinkedHashSetReverseIterator& operator++() { Superclass::operator--(); return *this; }
455 LinkedHashSetReverseIterator& operator--() { Superclass::operator++(); return *this; }
457 // Postfix ++ and -- intentionally omitted.
459 operator const_reverse_iterator() const { return *reinterpret_cast<const_reverse_iterator*>(this); }
461 template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
464 template<typename LinkedHashSetType>
465 class LinkedHashSetConstReverseIterator : public LinkedHashSetConstIterator<LinkedHashSetType> {
466 typedef LinkedHashSetConstIterator<LinkedHashSetType> Superclass;
467 typedef typename LinkedHashSetType::Node Node;
470 LinkedHashSetConstReverseIterator(const Node* position, const LinkedHashSetType* container)
471 : Superclass(position, container) { }
473 LinkedHashSetConstReverseIterator& operator++() { Superclass::operator--(); return *this; }
474 LinkedHashSetConstReverseIterator& operator--() { Superclass::operator++(); return *this; }
476 // Postfix ++ and -- intentionally omitted.
478 template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
481 template<typename T, typename U, typename V, typename W>
482 inline LinkedHashSet<T, U, V, W>::LinkedHashSet() { }
484 template<typename T, typename U, typename V, typename W>
485 inline LinkedHashSet<T, U, V, W>::LinkedHashSet(const LinkedHashSet& other)
488 const_iterator end = other.end();
489 for (const_iterator it = other.begin(); it != end; ++it)
493 template<typename T, typename U, typename V, typename W>
494 inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=(const LinkedHashSet& other)
496 LinkedHashSet tmp(other);
501 template<typename T, typename U, typename V, typename W>
502 inline void LinkedHashSet<T, U, V, W>::swap(LinkedHashSet& other)
504 m_impl.swap(other.m_impl);
505 swap(m_anchor, other.m_anchor);
508 template<typename T, typename U, typename V, typename Allocator>
509 inline LinkedHashSet<T, U, V, Allocator>::~LinkedHashSet()
511 // The destructor of m_anchor will implicitly be called here, which will
512 // unlink the anchor from the collection.
515 template<typename T, typename U, typename V, typename W>
516 inline T& LinkedHashSet<T, U, V, W>::first()
519 return firstNode()->m_value;
522 template<typename T, typename U, typename V, typename W>
523 inline const T& LinkedHashSet<T, U, V, W>::first() const
526 return firstNode()->m_value;
529 template<typename T, typename U, typename V, typename W>
530 inline void LinkedHashSet<T, U, V, W>::removeFirst()
533 m_impl.remove(static_cast<Node*>(m_anchor.m_next));
536 template<typename T, typename U, typename V, typename W>
537 inline T& LinkedHashSet<T, U, V, W>::last()
540 return lastNode()->m_value;
543 template<typename T, typename U, typename V, typename W>
544 inline const T& LinkedHashSet<T, U, V, W>::last() const
547 return lastNode()->m_value;
550 template<typename T, typename U, typename V, typename W>
551 inline void LinkedHashSet<T, U, V, W>::removeLast()
554 m_impl.remove(static_cast<Node*>(m_anchor.m_prev));
557 template<typename T, typename U, typename V, typename W>
558 inline typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::find(ValuePeekInType value)
560 LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::NodeHashFunctions, ValuePeekInType>(value);
563 return makeIterator(node);
566 template<typename T, typename U, typename V, typename W>
567 inline typename LinkedHashSet<T, U, V, W>::const_iterator LinkedHashSet<T, U, V, W>::find(ValuePeekInType value) const
569 const LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::NodeHashFunctions, ValuePeekInType>(value);
572 return makeConstIterator(node);
575 template<typename Translator>
576 struct LinkedHashSetTranslatorAdapter {
577 template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
578 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a.m_value, b); }
581 template<typename Value, typename U, typename V, typename W>
582 template<typename HashTranslator, typename T>
583 inline typename LinkedHashSet<Value, U, V, W>::iterator LinkedHashSet<Value, U, V, W>::find(const T& value)
585 typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions;
586 const LinkedHashSet::Node* node = m_impl.template lookup<TranslatedFunctions, const T&>(value);
589 return makeIterator(node);
592 template<typename Value, typename U, typename V, typename W>
593 template<typename HashTranslator, typename T>
594 inline typename LinkedHashSet<Value, U, V, W>::const_iterator LinkedHashSet<Value, U, V, W>::find(const T& value) const
596 typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions;
597 const LinkedHashSet::Node* node = m_impl.template lookup<TranslatedFunctions, const T&>(value);
600 return makeConstIterator(node);
603 template<typename Value, typename U, typename V, typename W>
604 template<typename HashTranslator, typename T>
605 inline bool LinkedHashSet<Value, U, V, W>::contains(const T& value) const
607 return m_impl.template contains<LinkedHashSetTranslatorAdapter<HashTranslator> >(value);
610 template<typename T, typename U, typename V, typename W>
611 inline bool LinkedHashSet<T, U, V, W>::contains(ValuePeekInType value) const
613 return m_impl.template contains<NodeHashFunctions>(value);
616 template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
617 typename LinkedHashSet<Value, HashFunctions, Traits, Allocator>::AddResult LinkedHashSet<Value, HashFunctions, Traits, Allocator>::add(ValuePeekInType value)
619 return m_impl.template add<NodeHashFunctions>(value, &m_anchor);
622 template<typename T, typename U, typename V, typename W>
623 typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::addReturnIterator(ValuePeekInType value)
625 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>(value, &m_anchor);
626 return makeIterator(result.storedValue);
629 template<typename T, typename U, typename V, typename W>
630 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::appendOrMoveToLast(ValuePeekInType value)
632 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>(value, &m_anchor);
633 Node* node = result.storedValue;
634 if (!result.isNewEntry) {
636 m_anchor.insertBefore(*node);
641 template<typename T, typename U, typename V, typename W>
642 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::prependOrMoveToFirst(ValuePeekInType value)
644 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>(value, m_anchor.m_next);
645 Node* node = result.storedValue;
646 if (!result.isNewEntry) {
648 m_anchor.insertAfter(*node);
653 template<typename T, typename U, typename V, typename W>
654 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::insertBefore(ValuePeekInType beforeValue, ValuePeekInType newValue)
656 return insertBefore(find(beforeValue), newValue);
659 template<typename T, typename U, typename V, typename W>
660 inline void LinkedHashSet<T, U, V, W>::remove(iterator it)
664 m_impl.remove(it.node());
667 template<typename T, typename U, typename V, typename W>
668 inline void LinkedHashSet<T, U, V, W>::remove(ValuePeekInType value)
674 struct IsWeak<LinkedHashSetNode<T> > {
675 static const bool value = IsWeak<T>::value;
678 inline void swap(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b)
680 swap(a.m_prev, b.m_prev);
681 swap(a.m_next, b.m_next);
683 b.m_next->m_prev = &b;
684 b.m_prev->m_next = &b;
687 a.m_next->m_prev = &a;
688 a.m_prev->m_next = &a;
693 inline void swap(LinkedHashSetNode<T>& a, LinkedHashSetNode<T>& b)
695 typedef LinkedHashSetNodeBase Base;
697 swap(static_cast<Base&>(a), static_cast<Base&>(b));
698 swap(a.m_value, b.m_value);
701 // Warning: After and while calling this you have a collection with deleted
702 // pointers. Consider using a smart pointer like OwnPtr and calling clear()
704 template<typename ValueType, typename T, typename U>
705 void deleteAllValues(const LinkedHashSet<ValueType, T, U>& set)
707 typedef typename LinkedHashSet<ValueType, T, U>::const_iterator iterator;
708 iterator end = set.end();
709 for (iterator it = set.begin(); it != end; ++it)
715 using WTF::LinkedHashSet;
717 #endif /* WTF_LinkedHashSet_h */