| /* | 
 |  * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved. | 
 |  * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com> | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Library General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2 of the License, or (at your option) any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |  * Library General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Library General Public License | 
 |  * along with this library; see the file COPYING.LIB.  If not, write to | 
 |  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 
 |  * Boston, MA 02110-1301, USA. | 
 |  * | 
 |  */ | 
 |  | 
 | #ifndef SKY_ENGINE_WTF_LISTHASHSET_H_ | 
 | #define SKY_ENGINE_WTF_LISTHASHSET_H_ | 
 |  | 
 | #include "sky/engine/wtf/DefaultAllocator.h" | 
 | #include "sky/engine/wtf/HashSet.h" | 
 | #include "sky/engine/wtf/OwnPtr.h" | 
 | #include "sky/engine/wtf/PassOwnPtr.h" | 
 |  | 
 | namespace WTF { | 
 |  | 
 |     // ListHashSet: Just like HashSet, this class provides a Set | 
 |     // interface - a collection of unique objects with O(1) insertion, | 
 |     // removal and test for containership. However, it also has an | 
 |     // order - iterating it will always give back values in the order | 
 |     // in which they are added. | 
 |  | 
 |     // Unlike iteration of most WTF Hash data structures, iteration is | 
 |     // guaranteed safe against mutation of the ListHashSet, except for | 
 |     // removal of the item currently pointed to by a given iterator. | 
 |  | 
 |     template<typename Value, size_t inlineCapacity, typename HashFunctions, typename Allocator> class ListHashSet; | 
 |  | 
 |     template<typename Set> class ListHashSetIterator; | 
 |     template<typename Set> class ListHashSetConstIterator; | 
 |     template<typename Set> class ListHashSetReverseIterator; | 
 |     template<typename Set> class ListHashSetConstReverseIterator; | 
 |  | 
 |     template<typename ValueArg> class ListHashSetNodeBase; | 
 |     template<typename ValueArg, typename Allocator> class ListHashSetNode; | 
 |     template<typename ValueArg, size_t inlineCapacity> struct ListHashSetAllocator; | 
 |  | 
 |     template<typename HashArg> struct ListHashSetNodeHashFunctions; | 
 |     template<typename HashArg> struct ListHashSetTranslator; | 
 |  | 
 |     // Don't declare a destructor for HeapAllocated ListHashSet. | 
 |     template<typename Derived, typename Allocator, bool isGarbageCollected> | 
 |     class ListHashSetDestructorBase; | 
 |  | 
 |     template<typename Derived, typename Allocator> | 
 |     class ListHashSetDestructorBase<Derived, Allocator, true> { | 
 |     protected: | 
 |         typename Allocator::AllocatorProvider m_allocatorProvider; | 
 |     }; | 
 |  | 
 |     template<typename Derived, typename Allocator> | 
 |     class ListHashSetDestructorBase<Derived, Allocator, false> { | 
 |     public: | 
 |         ~ListHashSetDestructorBase() { static_cast<Derived*>(this)->finalize(); } | 
 |     protected: | 
 |         typename Allocator::AllocatorProvider m_allocatorProvider; | 
 |     }; | 
 |  | 
 |     // Note that for a ListHashSet you cannot specify the HashTraits as a | 
 |     // template argument. It uses the default hash traits for the ValueArg | 
 |     // type. | 
 |     template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash, typename AllocatorArg = ListHashSetAllocator<ValueArg, inlineCapacity> > class ListHashSet | 
 |         : public ListHashSetDestructorBase<ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>, AllocatorArg, AllocatorArg::isGarbageCollected> { | 
 |         typedef AllocatorArg Allocator; | 
 |         WTF_USE_ALLOCATOR(ListHashSet, Allocator); | 
 |  | 
 |         typedef ListHashSetNode<ValueArg, Allocator> Node; | 
 |         typedef HashTraits<Node*> NodeTraits; | 
 |         typedef ListHashSetNodeHashFunctions<HashArg> NodeHash; | 
 |         typedef ListHashSetTranslator<HashArg> BaseTranslator; | 
 |  | 
 |         typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplType; | 
 |         typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeIterator; | 
 |         typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeConstIterator; | 
 |  | 
 |         typedef HashArg HashFunctions; | 
 |  | 
 |     public: | 
 |         typedef ValueArg ValueType; | 
 |         typedef HashTraits<ValueType> ValueTraits; | 
 |         typedef typename ValueTraits::PeekInType ValuePeekInType; | 
 |         typedef typename ValueTraits::PassInType ValuePassInType; | 
 |         typedef typename ValueTraits::PassOutType ValuePassOutType; | 
 |  | 
 |         typedef ListHashSetIterator<ListHashSet> iterator; | 
 |         typedef ListHashSetConstIterator<ListHashSet> const_iterator; | 
 |         friend class ListHashSetIterator<ListHashSet>; | 
 |         friend class ListHashSetConstIterator<ListHashSet>; | 
 |  | 
 |         typedef ListHashSetReverseIterator<ListHashSet> reverse_iterator; | 
 |         typedef ListHashSetConstReverseIterator<ListHashSet> const_reverse_iterator; | 
 |         friend class ListHashSetReverseIterator<ListHashSet>; | 
 |         friend class ListHashSetConstReverseIterator<ListHashSet>; | 
 |  | 
 |         template<typename ValueType> struct HashTableAddResult { | 
 |         HashTableAddResult(Node* storedValue, bool isNewEntry) : storedValue(storedValue), isNewEntry(isNewEntry) { } | 
 |             Node* storedValue; | 
 |             bool isNewEntry; | 
 |         }; | 
 |         typedef HashTableAddResult<ValueType> AddResult; | 
 |  | 
 |         ListHashSet(); | 
 |         ListHashSet(const ListHashSet&); | 
 |         ListHashSet& operator=(const ListHashSet&); | 
 |         void finalize(); | 
 |  | 
 |         void swap(ListHashSet&); | 
 |  | 
 |         unsigned size() const { return m_impl.size(); } | 
 |         unsigned capacity() const { return m_impl.capacity(); } | 
 |         bool isEmpty() const { return m_impl.isEmpty(); } | 
 |  | 
 |         iterator begin() { return makeIterator(m_head); } | 
 |         iterator end() { return makeIterator(0); } | 
 |         const_iterator begin() const { return makeConstIterator(m_head); } | 
 |         const_iterator end() const { return makeConstIterator(0); } | 
 |  | 
 |         reverse_iterator rbegin() { return makeReverseIterator(m_tail); } | 
 |         reverse_iterator rend() { return makeReverseIterator(0); } | 
 |         const_reverse_iterator rbegin() const { return makeConstReverseIterator(m_tail); } | 
 |         const_reverse_iterator rend() const { return makeConstReverseIterator(0); } | 
 |  | 
 |         ValueType& first(); | 
 |         const ValueType& first() const; | 
 |         void removeFirst(); | 
 |  | 
 |         ValueType& last(); | 
 |         const ValueType& last() const; | 
 |         void removeLast(); | 
 |  | 
 |         iterator find(ValuePeekInType); | 
 |         const_iterator find(ValuePeekInType) const; | 
 |         bool contains(ValuePeekInType) const; | 
 |  | 
 |         // An alternate version of find() that finds the object by hashing and comparing | 
 |         // with some other type, to avoid the cost of type conversion. | 
 |         // The HashTranslator interface is defined in HashSet. | 
 |         template<typename HashTranslator, typename T> iterator find(const T&); | 
 |         template<typename HashTranslator, typename T> const_iterator find(const T&) const; | 
 |         template<typename HashTranslator, typename T> bool contains(const T&) const; | 
 |  | 
 |         // The return value of add is a pair of a pointer to the stored value, | 
 |         // and a bool that is true if an new entry was added. | 
 |         AddResult add(ValuePassInType); | 
 |  | 
 |         // Same as add() except that the return value is an | 
 |         // iterator. Useful in cases where it's needed to have the | 
 |         // same return value as find() and where it's not possible to | 
 |         // use a pointer to the storedValue. | 
 |         iterator addReturnIterator(ValuePassInType); | 
 |  | 
 |         // Add the value to the end of the collection. If the value was already in | 
 |         // the list, it is moved to the end. | 
 |         AddResult appendOrMoveToLast(ValuePassInType); | 
 |  | 
 |         // Add the value to the beginning of the collection. If the value was already in | 
 |         // the list, it is moved to the beginning. | 
 |         AddResult prependOrMoveToFirst(ValuePassInType); | 
 |  | 
 |         AddResult insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue); | 
 |         AddResult insertBefore(iterator, ValuePassInType); | 
 |  | 
 |         void remove(ValuePeekInType value) { return remove(find(value)); } | 
 |         void remove(iterator); | 
 |         void clear(); | 
 |         template<typename Collection> | 
 |         void removeAll(const Collection& other) { WTF::removeAll(*this, other); } | 
 |  | 
 |         ValuePassOutType take(iterator); | 
 |         ValuePassOutType take(ValuePeekInType); | 
 |         ValuePassOutType takeFirst(); | 
 |  | 
 |     private: | 
 |         void unlink(Node*); | 
 |         void unlinkAndDelete(Node*); | 
 |         void appendNode(Node*); | 
 |         void prependNode(Node*); | 
 |         void insertNodeBefore(Node* beforeNode, Node* newNode); | 
 |         void deleteAllNodes(); | 
 |         Allocator* allocator() const { return this->m_allocatorProvider.get(); } | 
 |         void createAllocatorIfNeeded() { this->m_allocatorProvider.createAllocatorIfNeeded(); } | 
 |         void deallocate(Node* node) const { this->m_allocatorProvider.deallocate(node); } | 
 |  | 
 |         iterator makeIterator(Node* position) { return iterator(this, position); } | 
 |         const_iterator makeConstIterator(Node* position) const { return const_iterator(this, position); } | 
 |         reverse_iterator makeReverseIterator(Node* position) { return reverse_iterator(this, position); } | 
 |         const_reverse_iterator makeConstReverseIterator(Node* position) const { return const_reverse_iterator(this, position); } | 
 |  | 
 |         ImplType m_impl; | 
 |         Node* m_head; | 
 |         Node* m_tail; | 
 |     }; | 
 |  | 
 |     // ListHashSetNode has this base class to hold the members because the MSVC | 
 |     // compiler otherwise gets into circular template dependencies when trying | 
 |     // to do sizeof on a node. | 
 |     template<typename ValueArg> class ListHashSetNodeBase { | 
 |     protected: | 
 |         ListHashSetNodeBase(const ValueArg& value) | 
 |             : m_value(value) | 
 |             , m_prev(0) | 
 |             , m_next(0) | 
 | #if ENABLE(ASSERT) | 
 |             , m_isAllocated(true) | 
 | #endif | 
 |         { | 
 |         } | 
 |  | 
 |         template <typename U> | 
 |         ListHashSetNodeBase(const U& value) | 
 |             : m_value(value) | 
 |             , m_prev(0) | 
 |             , m_next(0) | 
 | #if ENABLE(ASSERT) | 
 |             , m_isAllocated(true) | 
 | #endif | 
 |         { | 
 |         } | 
 |  | 
 |     public: | 
 |         ValueArg m_value; | 
 |         ListHashSetNodeBase* m_prev; | 
 |         ListHashSetNodeBase* m_next; | 
 | #if ENABLE(ASSERT) | 
 |         bool m_isAllocated; | 
 | #endif | 
 |     }; | 
 |  | 
 |     // This allocator is only used for non-Heap ListHashSets. | 
 |     template<typename ValueArg, size_t inlineCapacity> | 
 |     struct ListHashSetAllocator : public DefaultAllocator { | 
 |         typedef DefaultAllocator TableAllocator; | 
 |         typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node; | 
 |         typedef ListHashSetNodeBase<ValueArg> NodeBase; | 
 |         class AllocatorProvider { | 
 |         public: | 
 |             void createAllocatorIfNeeded() | 
 |             { | 
 |                 if (!m_allocator) | 
 |                     m_allocator = adoptPtr(new ListHashSetAllocator); | 
 |             } | 
 |  | 
 |             void swap(AllocatorProvider& other) | 
 |             { | 
 |                 m_allocator.swap(other.m_allocator); | 
 |             } | 
 |  | 
 |             void deallocate(Node* node) const | 
 |             { | 
 |                 ASSERT(m_allocator); | 
 |                 m_allocator->deallocate(node); | 
 |             } | 
 |  | 
 |             ListHashSetAllocator* get() const | 
 |             { | 
 |                 ASSERT(m_allocator); | 
 |                 return m_allocator.get(); | 
 |             } | 
 |  | 
 |         private: | 
 |             OwnPtr<ListHashSetAllocator> m_allocator; | 
 |         }; | 
 |  | 
 |         ListHashSetAllocator() | 
 |             : m_freeList(pool()) | 
 |             , m_isDoneWithInitialFreeList(false) | 
 |         { | 
 |             memset(m_pool.buffer, 0, sizeof(m_pool.buffer)); | 
 |         } | 
 |  | 
 |         Node* allocateNode() | 
 |         { | 
 |             Node* result = m_freeList; | 
 |  | 
 |             if (!result) | 
 |                 return static_cast<Node*>(fastMalloc(sizeof(NodeBase))); | 
 |  | 
 |             ASSERT(!result->m_isAllocated); | 
 |  | 
 |             Node* next = result->next(); | 
 |             ASSERT(!next || !next->m_isAllocated); | 
 |             if (!next && !m_isDoneWithInitialFreeList) { | 
 |                 next = result + 1; | 
 |                 if (next == pastPool()) { | 
 |                     m_isDoneWithInitialFreeList = true; | 
 |                     next = 0; | 
 |                 } else { | 
 |                     ASSERT(inPool(next)); | 
 |                     ASSERT(!next->m_isAllocated); | 
 |                 } | 
 |             } | 
 |             m_freeList = next; | 
 |  | 
 |             return result; | 
 |         } | 
 |  | 
 |         void deallocate(Node* node) | 
 |         { | 
 |             if (inPool(node)) { | 
 | #if ENABLE(ASSERT) | 
 |                 node->m_isAllocated = false; | 
 | #endif | 
 |                 node->m_next = m_freeList; | 
 |                 m_freeList = node; | 
 |                 return; | 
 |             } | 
 |  | 
 |             fastFree(node); | 
 |         } | 
 |  | 
 |         bool inPool(Node* node) | 
 |         { | 
 |             return node >= pool() && node < pastPool(); | 
 |         } | 
 |  | 
 |     private: | 
 |         Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.buffer); } | 
 |         Node* pastPool() { return pool() + m_poolSize; } | 
 |  | 
 |         Node* m_freeList; | 
 |         bool m_isDoneWithInitialFreeList; | 
 | #if defined(MEMORY_SANITIZER_INITIAL_SIZE) | 
 |         // The allocation pool for nodes is one big chunk that ASAN has no | 
 |         // insight into, so it can cloak errors. Make it as small as possible | 
 |         // to force nodes to be allocated individually where ASAN can see them. | 
 |         static const size_t m_poolSize = 1; | 
 | #else | 
 |         static const size_t m_poolSize = inlineCapacity; | 
 | #endif | 
 |         AlignedBuffer<sizeof(NodeBase) * m_poolSize, WTF_ALIGN_OF(NodeBase)> m_pool; | 
 |     }; | 
 |  | 
 |     template<typename ValueArg, typename AllocatorArg> class ListHashSetNode : public ListHashSetNodeBase<ValueArg> { | 
 |     public: | 
 |         typedef AllocatorArg NodeAllocator; | 
 |         typedef ValueArg Value; | 
 |  | 
 |         template <typename U> | 
 |         ListHashSetNode(U value) | 
 |             : ListHashSetNodeBase<ValueArg>(value) { } | 
 |  | 
 |         void* operator new(size_t, NodeAllocator* allocator) | 
 |         { | 
 |             COMPILE_ASSERT(sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<ValueArg>), PleaseAddAnyFieldsToTheBase); | 
 |             return allocator->allocateNode(); | 
 |         } | 
 |  | 
 |         void setWasAlreadyDestructed() | 
 |         { | 
 |             if (NodeAllocator::isGarbageCollected && HashTraits<ValueArg>::needsDestruction) | 
 |                 this->m_prev = unlinkedNodePointer(); | 
 |         } | 
 |  | 
 |         bool wasAlreadyDestructed() const | 
 |         { | 
 |             ASSERT(NodeAllocator::isGarbageCollected); | 
 |             return this->m_prev == unlinkedNodePointer(); | 
 |         } | 
 |  | 
 |         static void finalize(void* pointer) | 
 |         { | 
 |             ASSERT(HashTraits<ValueArg>::needsDestruction); // No need to waste time calling finalize if it's not needed. | 
 |             ListHashSetNode* self = reinterpret_cast_ptr<ListHashSetNode*>(pointer); | 
 |  | 
 |             // Check whether this node was already destructed before being | 
 |             // unlinked from the collection. | 
 |             if (self->wasAlreadyDestructed()) | 
 |                 return; | 
 |  | 
 |             self->m_value.~ValueArg(); | 
 |         } | 
 |  | 
 |         void destroy(NodeAllocator* allocator) | 
 |         { | 
 |             this->~ListHashSetNode(); | 
 |             setWasAlreadyDestructed(); | 
 |             allocator->deallocate(this); | 
 |         } | 
 |  | 
 |         ListHashSetNode* next() const { return reinterpret_cast<ListHashSetNode*>(this->m_next); } | 
 |         ListHashSetNode* prev() const { return reinterpret_cast<ListHashSetNode*>(this->m_prev); } | 
 |  | 
 |         // Don't add fields here, the ListHashSetNodeBase and this should have | 
 |         // the same size. | 
 |  | 
 |         static ListHashSetNode* unlinkedNodePointer() { return reinterpret_cast<ListHashSetNode*>(-1); } | 
 |  | 
 |         template<typename HashArg> | 
 |         friend struct ListHashSetNodeHashFunctions; | 
 |     }; | 
 |  | 
 |     template<typename HashArg> struct ListHashSetNodeHashFunctions { | 
 |         template<typename T> static unsigned hash(const T& key) { return HashArg::hash(key->m_value); } | 
 |         template<typename T> static bool equal(const T& a, const T& b) { return HashArg::equal(a->m_value, b->m_value); } | 
 |         static const bool safeToCompareToEmptyOrDeleted = false; | 
 |     }; | 
 |  | 
 |     template<typename Set> class ListHashSetIterator { | 
 |     private: | 
 |         typedef typename Set::const_iterator const_iterator; | 
 |         typedef typename Set::Node Node; | 
 |         typedef typename Set::ValueType ValueType; | 
 |         typedef ValueType& ReferenceType; | 
 |         typedef ValueType* PointerType; | 
 |  | 
 |         ListHashSetIterator(const Set* set, Node* position) : m_iterator(set, position) { } | 
 |  | 
 |     public: | 
 |         ListHashSetIterator() { } | 
 |  | 
 |         // default copy, assignment and destructor are OK | 
 |  | 
 |         PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } | 
 |         ReferenceType operator*() const { return *get(); } | 
 |         PointerType operator->() const { return get(); } | 
 |  | 
 |         ListHashSetIterator& operator++() { ++m_iterator; return *this; } | 
 |         ListHashSetIterator& operator--() { --m_iterator; return *this; } | 
 |  | 
 |         // Postfix ++ and -- intentionally omitted. | 
 |  | 
 |         // Comparison. | 
 |         bool operator==(const ListHashSetIterator& other) const { return m_iterator == other.m_iterator; } | 
 |         bool operator!=(const ListHashSetIterator& other) const { return m_iterator != other.m_iterator; } | 
 |  | 
 |         operator const_iterator() const { return m_iterator; } | 
 |  | 
 |     private: | 
 |         Node* node() { return m_iterator.node(); } | 
 |  | 
 |         const_iterator m_iterator; | 
 |  | 
 |         template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |         friend class ListHashSet; | 
 |     }; | 
 |  | 
 |     template<typename Set> | 
 |     class ListHashSetConstIterator { | 
 |     private: | 
 |         typedef typename Set::const_iterator const_iterator; | 
 |         typedef typename Set::Node Node; | 
 |         typedef typename Set::ValueType ValueType; | 
 |         typedef const ValueType& ReferenceType; | 
 |         typedef const ValueType* PointerType; | 
 |  | 
 |         friend class ListHashSetIterator<Set>; | 
 |  | 
 |         ListHashSetConstIterator(const Set* set, Node* position) | 
 |             : m_set(set) | 
 |             , m_position(position) | 
 |         { | 
 |         } | 
 |  | 
 |     public: | 
 |         ListHashSetConstIterator() | 
 |         { | 
 |         } | 
 |  | 
 |         PointerType get() const | 
 |         { | 
 |             return &m_position->m_value; | 
 |         } | 
 |         ReferenceType operator*() const { return *get(); } | 
 |         PointerType operator->() const { return get(); } | 
 |  | 
 |         ListHashSetConstIterator& operator++() | 
 |         { | 
 |             ASSERT(m_position != 0); | 
 |             m_position = m_position->next(); | 
 |             return *this; | 
 |         } | 
 |  | 
 |         ListHashSetConstIterator& operator--() | 
 |         { | 
 |             ASSERT(m_position != m_set->m_head); | 
 |             if (!m_position) | 
 |                 m_position = m_set->m_tail; | 
 |             else | 
 |                 m_position = m_position->prev(); | 
 |             return *this; | 
 |         } | 
 |  | 
 |         // Postfix ++ and -- intentionally omitted. | 
 |  | 
 |         // Comparison. | 
 |         bool operator==(const ListHashSetConstIterator& other) const | 
 |         { | 
 |             return m_position == other.m_position; | 
 |         } | 
 |         bool operator!=(const ListHashSetConstIterator& other) const | 
 |         { | 
 |             return m_position != other.m_position; | 
 |         } | 
 |  | 
 |     private: | 
 |         Node* node() { return m_position; } | 
 |  | 
 |         const Set* m_set; | 
 |         Node* m_position; | 
 |  | 
 |         template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |         friend class ListHashSet; | 
 |     }; | 
 |  | 
 |     template<typename Set> | 
 |     class ListHashSetReverseIterator { | 
 |     private: | 
 |         typedef typename Set::const_reverse_iterator const_reverse_iterator; | 
 |         typedef typename Set::Node Node; | 
 |         typedef typename Set::ValueType ValueType; | 
 |         typedef ValueType& ReferenceType; | 
 |         typedef ValueType* PointerType; | 
 |  | 
 |         ListHashSetReverseIterator(const Set* set, Node* position) : m_iterator(set, position) { } | 
 |  | 
 |     public: | 
 |         ListHashSetReverseIterator() { } | 
 |  | 
 |         // default copy, assignment and destructor are OK | 
 |  | 
 |         PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } | 
 |         ReferenceType operator*() const { return *get(); } | 
 |         PointerType operator->() const { return get(); } | 
 |  | 
 |         ListHashSetReverseIterator& operator++() { ++m_iterator; return *this; } | 
 |         ListHashSetReverseIterator& operator--() { --m_iterator; return *this; } | 
 |  | 
 |         // Postfix ++ and -- intentionally omitted. | 
 |  | 
 |         // Comparison. | 
 |         bool operator==(const ListHashSetReverseIterator& other) const { return m_iterator == other.m_iterator; } | 
 |         bool operator!=(const ListHashSetReverseIterator& other) const { return m_iterator != other.m_iterator; } | 
 |  | 
 |         operator const_reverse_iterator() const { return m_iterator; } | 
 |  | 
 |     private: | 
 |         Node* node() { return m_iterator.node(); } | 
 |  | 
 |         const_reverse_iterator m_iterator; | 
 |  | 
 |         template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |         friend class ListHashSet; | 
 |     }; | 
 |  | 
 |     template<typename Set> class ListHashSetConstReverseIterator { | 
 |     private: | 
 |         typedef typename Set::reverse_iterator reverse_iterator; | 
 |         typedef typename Set::Node Node; | 
 |         typedef typename Set::ValueType ValueType; | 
 |         typedef const ValueType& ReferenceType; | 
 |         typedef const ValueType* PointerType; | 
 |  | 
 |         friend class ListHashSetReverseIterator<Set>; | 
 |  | 
 |         ListHashSetConstReverseIterator(const Set* set, Node* position) | 
 |             : m_set(set) | 
 |             , m_position(position) | 
 |         { | 
 |         } | 
 |  | 
 |     public: | 
 |         ListHashSetConstReverseIterator() | 
 |         { | 
 |         } | 
 |  | 
 |         PointerType get() const | 
 |         { | 
 |             return &m_position->m_value; | 
 |         } | 
 |         ReferenceType operator*() const { return *get(); } | 
 |         PointerType operator->() const { return get(); } | 
 |  | 
 |         ListHashSetConstReverseIterator& operator++() | 
 |         { | 
 |             ASSERT(m_position != 0); | 
 |             m_position = m_position->prev(); | 
 |             return *this; | 
 |         } | 
 |  | 
 |         ListHashSetConstReverseIterator& operator--() | 
 |         { | 
 |             ASSERT(m_position != m_set->m_tail); | 
 |             if (!m_position) | 
 |                 m_position = m_set->m_head; | 
 |             else | 
 |                 m_position = m_position->next(); | 
 |             return *this; | 
 |         } | 
 |  | 
 |         // Postfix ++ and -- intentionally omitted. | 
 |  | 
 |         // Comparison. | 
 |         bool operator==(const ListHashSetConstReverseIterator& other) const | 
 |         { | 
 |             return m_position == other.m_position; | 
 |         } | 
 |         bool operator!=(const ListHashSetConstReverseIterator& other) const | 
 |         { | 
 |             return m_position != other.m_position; | 
 |         } | 
 |  | 
 |     private: | 
 |         Node* node() { return m_position; } | 
 |  | 
 |         const Set* m_set; | 
 |         Node* m_position; | 
 |  | 
 |         template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |         friend class ListHashSet; | 
 |     }; | 
 |  | 
 |     template<typename HashFunctions> | 
 |     struct ListHashSetTranslator { | 
 |         template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); } | 
 |         template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); } | 
 |         template<typename T, typename U, typename V> static void translate(T*& location, const U& key, const V& allocator) | 
 |         { | 
 |             location = new (const_cast<V*>(&allocator)) T(key); | 
 |         } | 
 |     }; | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet() | 
 |         : m_head(0) | 
 |         , m_tail(0) | 
 |     { | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(const ListHashSet& other) | 
 |         : m_head(0) | 
 |         , m_tail(0) | 
 |     { | 
 |         const_iterator end = other.end(); | 
 |         for (const_iterator it = other.begin(); it != end; ++it) | 
 |             add(*it); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline ListHashSet<T, inlineCapacity, U, V>& ListHashSet<T, inlineCapacity, U, V>::operator=(const ListHashSet& other) | 
 |     { | 
 |         ListHashSet tmp(other); | 
 |         swap(tmp); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline void ListHashSet<T, inlineCapacity, U, V>::swap(ListHashSet& other) | 
 |     { | 
 |         m_impl.swap(other.m_impl); | 
 |         std::swap(m_head, other.m_head); | 
 |         std::swap(m_tail, other.m_tail); | 
 |         this->m_allocatorProvider.swap(other.m_allocatorProvider); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline void ListHashSet<T, inlineCapacity, U, V>::finalize() | 
 |     { | 
 |         COMPILE_ASSERT(!Allocator::isGarbageCollected, FinalizeOnHeapAllocatedListHashSetShouldNeverBeCalled); | 
 |         deleteAllNodes(); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline T& ListHashSet<T, inlineCapacity, U, V>::first() | 
 |     { | 
 |         ASSERT(!isEmpty()); | 
 |         return m_head->m_value; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline void ListHashSet<T, inlineCapacity, U, V>::removeFirst() | 
 |     { | 
 |         ASSERT(!isEmpty()); | 
 |         m_impl.remove(m_head); | 
 |         unlinkAndDelete(m_head); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline const T& ListHashSet<T, inlineCapacity, U, V>::first() const | 
 |     { | 
 |         ASSERT(!isEmpty()); | 
 |         return m_head->m_value; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline T& ListHashSet<T, inlineCapacity, U, V>::last() | 
 |     { | 
 |         ASSERT(!isEmpty()); | 
 |         return m_tail->m_value; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline const T& ListHashSet<T, inlineCapacity, U, V>::last() const | 
 |     { | 
 |         ASSERT(!isEmpty()); | 
 |         return m_tail->m_value; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline void ListHashSet<T, inlineCapacity, U, V>::removeLast() | 
 |     { | 
 |         ASSERT(!isEmpty()); | 
 |         m_impl.remove(m_tail); | 
 |         unlinkAndDelete(m_tail); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) | 
 |     { | 
 |         ImplTypeIterator it = m_impl.template find<BaseTranslator>(value); | 
 |         if (it == m_impl.end()) | 
 |             return end(); | 
 |         return makeIterator(*it); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline typename ListHashSet<T, inlineCapacity, U, V>::const_iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) const | 
 |     { | 
 |         ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value); | 
 |         if (it == m_impl.end()) | 
 |             return end(); | 
 |         return makeConstIterator(*it); | 
 |     } | 
 |  | 
 |     template<typename Translator> | 
 |     struct ListHashSetTranslatorAdapter { | 
 |         template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); } | 
 |         template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); } | 
 |     }; | 
 |  | 
 |     template<typename ValueType, size_t inlineCapacity, typename U, typename V> | 
 |     template<typename HashTranslator, typename T> | 
 |     inline typename ListHashSet<ValueType, inlineCapacity, U, V>::iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) | 
 |     { | 
 |         ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); | 
 |         if (it == m_impl.end()) | 
 |             return end(); | 
 |         return makeIterator(*it); | 
 |     } | 
 |  | 
 |     template<typename ValueType, size_t inlineCapacity, typename U, typename V> | 
 |     template<typename HashTranslator, typename T> | 
 |     inline typename ListHashSet<ValueType, inlineCapacity, U, V>::const_iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) const | 
 |     { | 
 |         ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); | 
 |         if (it == m_impl.end()) | 
 |             return end(); | 
 |         return makeConstIterator(*it); | 
 |     } | 
 |  | 
 |     template<typename ValueType, size_t inlineCapacity, typename U, typename V> | 
 |     template<typename HashTranslator, typename T> | 
 |     inline bool ListHashSet<ValueType, inlineCapacity, U, V>::contains(const T& value) const | 
 |     { | 
 |         return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator> >(value); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline bool ListHashSet<T, inlineCapacity, U, V>::contains(ValuePeekInType value) const | 
 |     { | 
 |         return m_impl.template contains<BaseTranslator>(value); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::add(ValuePassInType value) | 
 |     { | 
 |         createAllocatorIfNeeded(); | 
 |         // The second argument is a const ref. This is useful for the HashTable | 
 |         // because it lets it take lvalues by reference, but for our purposes | 
 |         // it's inconvenient, since it constrains us to be const, whereas the | 
 |         // allocator actually changes when it does allocations. | 
 |         typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, *this->allocator()); | 
 |         if (result.isNewEntry) | 
 |             appendNode(*result.storedValue); | 
 |         return AddResult(*result.storedValue, result.isNewEntry); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::addReturnIterator(ValuePassInType value) | 
 |     { | 
 |         return makeIterator(add(value).storedValue); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::appendOrMoveToLast(ValuePassInType value) | 
 |     { | 
 |         createAllocatorIfNeeded(); | 
 |         typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, *this->allocator()); | 
 |         Node* node = *result.storedValue; | 
 |         if (!result.isNewEntry) | 
 |             unlink(node); | 
 |         appendNode(node); | 
 |         return AddResult(*result.storedValue, result.isNewEntry); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::prependOrMoveToFirst(ValuePassInType value) | 
 |     { | 
 |         createAllocatorIfNeeded(); | 
 |         typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, *this->allocator()); | 
 |         Node* node = *result.storedValue; | 
 |         if (!result.isNewEntry) | 
 |             unlink(node); | 
 |         prependNode(node); | 
 |         return AddResult(*result.storedValue, result.isNewEntry); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(iterator it, ValuePassInType newValue) | 
 |     { | 
 |         createAllocatorIfNeeded(); | 
 |         typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(newValue, *this->allocator()); | 
 |         if (result.isNewEntry) | 
 |             insertNodeBefore(it.node(), *result.storedValue); | 
 |         return AddResult(*result.storedValue, result.isNewEntry); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue) | 
 |     { | 
 |         createAllocatorIfNeeded(); | 
 |         return insertBefore(find(beforeValue), newValue); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline void ListHashSet<T, inlineCapacity, U, V>::remove(iterator it) | 
 |     { | 
 |         if (it == end()) | 
 |             return; | 
 |         m_impl.remove(it.node()); | 
 |         unlinkAndDelete(it.node()); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     inline void ListHashSet<T, inlineCapacity, U, V>::clear() | 
 |     { | 
 |         deleteAllNodes(); | 
 |         m_impl.clear(); | 
 |         m_head = 0; | 
 |         m_tail = 0; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(iterator it) | 
 |     { | 
 |         if (it == end()) | 
 |             return ValueTraits::emptyValue(); | 
 |  | 
 |         m_impl.remove(it.node()); | 
 |         ValuePassOutType result = ValueTraits::passOut(it.node()->m_value); | 
 |         unlinkAndDelete(it.node()); | 
 |  | 
 |         return result; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(ValuePeekInType value) | 
 |     { | 
 |         return take(find(value)); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::takeFirst() | 
 |     { | 
 |         ASSERT(!isEmpty()); | 
 |         m_impl.remove(m_head); | 
 |         ValuePassOutType result = ValueTraits::passOut(m_head->m_value); | 
 |         unlinkAndDelete(m_head); | 
 |  | 
 |         return result; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename Allocator> | 
 |     void ListHashSet<T, inlineCapacity, U, Allocator>::unlink(Node* node) | 
 |     { | 
 |         if (!node->m_prev) { | 
 |             ASSERT(node == m_head); | 
 |             m_head = node->next(); | 
 |         } else { | 
 |             ASSERT(node != m_head); | 
 |             node->m_prev->m_next = node->m_next; | 
 |         } | 
 |  | 
 |         if (!node->m_next) { | 
 |             ASSERT(node == m_tail); | 
 |             m_tail = node->prev(); | 
 |         } else { | 
 |             ASSERT(node != m_tail); | 
 |             node->m_next->m_prev = node->m_prev; | 
 |         } | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     void ListHashSet<T, inlineCapacity, U, V>::unlinkAndDelete(Node* node) | 
 |     { | 
 |         unlink(node); | 
 |         node->destroy(this->allocator()); | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     void ListHashSet<T, inlineCapacity, U, V>::appendNode(Node* node) | 
 |     { | 
 |         node->m_prev = m_tail; | 
 |         node->m_next = 0; | 
 |  | 
 |         if (m_tail) { | 
 |             ASSERT(m_head); | 
 |             m_tail->m_next = node; | 
 |         } else { | 
 |             ASSERT(!m_head); | 
 |             m_head = node; | 
 |         } | 
 |  | 
 |         m_tail = node; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     void ListHashSet<T, inlineCapacity, U, V>::prependNode(Node* node) | 
 |     { | 
 |         node->m_prev = 0; | 
 |         node->m_next = m_head; | 
 |  | 
 |         if (m_head) | 
 |             m_head->m_prev = node; | 
 |         else | 
 |             m_tail = node; | 
 |  | 
 |         m_head = node; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     void ListHashSet<T, inlineCapacity, U, V>::insertNodeBefore(Node* beforeNode, Node* newNode) | 
 |     { | 
 |         if (!beforeNode) | 
 |             return appendNode(newNode); | 
 |  | 
 |         newNode->m_next = beforeNode; | 
 |         newNode->m_prev = beforeNode->m_prev; | 
 |         if (beforeNode->m_prev) | 
 |             beforeNode->m_prev->m_next = newNode; | 
 |         beforeNode->m_prev = newNode; | 
 |  | 
 |         if (!newNode->m_prev) | 
 |             m_head = newNode; | 
 |     } | 
 |  | 
 |     template<typename T, size_t inlineCapacity, typename U, typename V> | 
 |     void ListHashSet<T, inlineCapacity, U, V>::deleteAllNodes() | 
 |     { | 
 |         if (!m_head) | 
 |             return; | 
 |  | 
 |         for (Node* node = m_head, *next = m_head->next(); node; node = next, next = node ? node->next() : 0) | 
 |             node->destroy(this->allocator()); | 
 |     } | 
 |  | 
 | } // namespace WTF | 
 |  | 
 | using WTF::ListHashSet; | 
 |  | 
 | #endif  // SKY_ENGINE_WTF_LISTHASHSET_H_ |