Index: third_party/WebKit/Source/wtf/LinkedHashSet.h |
diff --git a/third_party/WebKit/Source/wtf/LinkedHashSet.h b/third_party/WebKit/Source/wtf/LinkedHashSet.h |
index f0e58176bf303794a1bd3faa4042af17f0bcf5af..534e242e60742bd8d2ce5efad30a3c6e44c5304b 100644 |
--- a/third_party/WebKit/Source/wtf/LinkedHashSet.h |
+++ b/third_party/WebKit/Source/wtf/LinkedHashSet.h |
@@ -1,938 +1,9 @@ |
-/* |
- * 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. |
- * |
- */ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
-#ifndef WTF_LinkedHashSet_h |
-#define WTF_LinkedHashSet_h |
+#include "platform/wtf/LinkedHashSet.h" |
-#include "wtf/AddressSanitizer.h" |
-#include "wtf/HashSet.h" |
-#include "wtf/allocator/PartitionAllocator.h" |
- |
-namespace WTF { |
- |
-// LinkedHashSet: 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 ListHashSet, but like most WTF collections, iteration is NOT safe |
-// against mutation of the LinkedHashSet. |
- |
-template <typename Value, |
- typename HashFunctions, |
- typename HashTraits, |
- typename Allocator> |
-class LinkedHashSet; |
- |
-template <typename LinkedHashSet> |
-class LinkedHashSetIterator; |
-template <typename LinkedHashSet> |
-class LinkedHashSetConstIterator; |
-template <typename LinkedHashSet> |
-class LinkedHashSetReverseIterator; |
-template <typename LinkedHashSet> |
-class LinkedHashSetConstReverseIterator; |
- |
-template <typename Value, typename HashFunctions, typename Allocator> |
-struct LinkedHashSetTranslator; |
-template <typename Value, typename Allocator> |
-struct LinkedHashSetExtractor; |
-template <typename Value, typename ValueTraits, typename Allocator> |
-struct LinkedHashSetTraits; |
- |
-class LinkedHashSetNodeBase { |
- DISALLOW_NEW(); |
- |
- public: |
- LinkedHashSetNodeBase() : m_prev(this), m_next(this) {} |
- |
- NO_SANITIZE_ADDRESS |
- void unlink() { |
- if (!m_next) |
- return; |
- DCHECK(m_prev); |
- DCHECK(m_next->m_prev == this); |
- DCHECK(m_prev->m_next == this); |
- m_next->m_prev = m_prev; |
- m_prev->m_next = m_next; |
- } |
- |
- ~LinkedHashSetNodeBase() { unlink(); } |
- |
- void insertBefore(LinkedHashSetNodeBase& other) { |
- other.m_next = this; |
- other.m_prev = m_prev; |
- m_prev->m_next = &other; |
- m_prev = &other; |
- DCHECK(other.m_next); |
- DCHECK(other.m_prev); |
- DCHECK(m_next); |
- DCHECK(m_prev); |
- } |
- |
- void insertAfter(LinkedHashSetNodeBase& other) { |
- other.m_prev = this; |
- other.m_next = m_next; |
- m_next->m_prev = &other; |
- m_next = &other; |
- DCHECK(other.m_next); |
- DCHECK(other.m_prev); |
- DCHECK(m_next); |
- DCHECK(m_prev); |
- } |
- |
- LinkedHashSetNodeBase(LinkedHashSetNodeBase* prev, |
- LinkedHashSetNodeBase* next) |
- : m_prev(prev), m_next(next) { |
- DCHECK((prev && next) || (!prev && !next)); |
- } |
- |
- LinkedHashSetNodeBase* m_prev; |
- LinkedHashSetNodeBase* m_next; |
- |
- protected: |
- // If we take a copy of a node we can't copy the next and prev pointers, |
- // since they point to something that does not point at us. This is used |
- // inside the shouldExpand() "if" in HashTable::add. |
- LinkedHashSetNodeBase(const LinkedHashSetNodeBase& other) |
- : m_prev(0), m_next(0) {} |
- |
- LinkedHashSetNodeBase(LinkedHashSetNodeBase&& other) |
- : m_prev(other.m_prev), m_next(other.m_next) { |
- other.m_prev = nullptr; |
- other.m_next = nullptr; |
- if (m_next) { |
- m_prev->m_next = this; |
- m_next->m_prev = this; |
- } |
- } |
- |
- private: |
- // Should not be used. |
- LinkedHashSetNodeBase& operator=(const LinkedHashSetNodeBase& other); |
-}; |
- |
-template <typename ValueArg, typename Allocator> |
-class LinkedHashSetNode : public LinkedHashSetNodeBase { |
- DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
- |
- public: |
- LinkedHashSetNode(const ValueArg& value, |
- LinkedHashSetNodeBase* prev, |
- LinkedHashSetNodeBase* next) |
- : LinkedHashSetNodeBase(prev, next), m_value(value) {} |
- |
- LinkedHashSetNode(LinkedHashSetNode&& other) |
- : LinkedHashSetNodeBase(std::move(other)), |
- m_value(std::move(other.m_value)) {} |
- |
- ValueArg m_value; |
- |
- private: |
- WTF_MAKE_NONCOPYABLE(LinkedHashSetNode); |
-}; |
- |
-template <typename ValueArg, |
- typename HashFunctions = typename DefaultHash<ValueArg>::Hash, |
- typename TraitsArg = HashTraits<ValueArg>, |
- typename Allocator = PartitionAllocator> |
-class LinkedHashSet { |
- USE_ALLOCATOR(LinkedHashSet, Allocator); |
- |
- private: |
- typedef ValueArg Value; |
- typedef TraitsArg Traits; |
- typedef LinkedHashSetNode<Value, Allocator> Node; |
- typedef LinkedHashSetNodeBase NodeBase; |
- typedef LinkedHashSetTranslator<Value, HashFunctions, Allocator> |
- NodeHashFunctions; |
- typedef LinkedHashSetTraits<Value, Traits, Allocator> NodeHashTraits; |
- |
- typedef HashTable<Node, |
- Node, |
- IdentityExtractor, |
- NodeHashFunctions, |
- NodeHashTraits, |
- NodeHashTraits, |
- Allocator> |
- ImplType; |
- |
- public: |
- typedef LinkedHashSetIterator<LinkedHashSet> iterator; |
- friend class LinkedHashSetIterator<LinkedHashSet>; |
- typedef LinkedHashSetConstIterator<LinkedHashSet> const_iterator; |
- friend class LinkedHashSetConstIterator<LinkedHashSet>; |
- |
- typedef LinkedHashSetReverseIterator<LinkedHashSet> reverse_iterator; |
- friend class LinkedHashSetReverseIterator<LinkedHashSet>; |
- typedef LinkedHashSetConstReverseIterator<LinkedHashSet> |
- const_reverse_iterator; |
- friend class LinkedHashSetConstReverseIterator<LinkedHashSet>; |
- |
- struct AddResult final { |
- STACK_ALLOCATED(); |
- AddResult(const typename ImplType::AddResult& hashTableAddResult) |
- : storedValue(&hashTableAddResult.storedValue->m_value), |
- isNewEntry(hashTableAddResult.isNewEntry) {} |
- |
- Value* storedValue; |
- bool isNewEntry; |
- }; |
- |
- typedef typename HashTraits<Value>::PeekInType ValuePeekInType; |
- |
- LinkedHashSet(); |
- LinkedHashSet(const LinkedHashSet&); |
- LinkedHashSet(LinkedHashSet&&); |
- LinkedHashSet& operator=(const LinkedHashSet&); |
- LinkedHashSet& operator=(LinkedHashSet&&); |
- |
- // Needs finalization. The anchor needs to unlink itself from the chain. |
- ~LinkedHashSet(); |
- |
- static void finalize(void* pointer) { |
- reinterpret_cast<LinkedHashSet*>(pointer)->~LinkedHashSet(); |
- } |
- void finalizeGarbageCollectedObject() { finalize(this); } |
- |
- void swap(LinkedHashSet&); |
- |
- 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(firstNode()); } |
- iterator end() { return makeIterator(anchor()); } |
- const_iterator begin() const { return makeConstIterator(firstNode()); } |
- const_iterator end() const { return makeConstIterator(anchor()); } |
- |
- reverse_iterator rbegin() { return makeReverseIterator(lastNode()); } |
- reverse_iterator rend() { return makeReverseIterator(anchor()); } |
- const_reverse_iterator rbegin() const { |
- return makeConstReverseIterator(lastNode()); |
- } |
- const_reverse_iterator rend() const { |
- return makeConstReverseIterator(anchor()); |
- } |
- |
- Value& front(); |
- const Value& front() const; |
- void removeFirst(); |
- |
- Value& back(); |
- const Value& back() const; |
- void pop_back(); |
- |
- 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 insert is a pair of a pointer to the stored value, |
- // and a bool that is true if an new entry was added. |
- template <typename IncomingValueType> |
- AddResult insert(IncomingValueType&&); |
- |
- // Same as insert() 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. |
- template <typename IncomingValueType> |
- iterator addReturnIterator(IncomingValueType&&); |
- |
- // Add the value to the end of the collection. If the value was already in |
- // the list, it is moved to the end. |
- template <typename IncomingValueType> |
- AddResult appendOrMoveToLast(IncomingValueType&&); |
- |
- // Add the value to the beginning of the collection. If the value was already |
- // in the list, it is moved to the beginning. |
- template <typename IncomingValueType> |
- AddResult prependOrMoveToFirst(IncomingValueType&&); |
- |
- template <typename IncomingValueType> |
- AddResult insertBefore(ValuePeekInType beforeValue, |
- IncomingValueType&& newValue); |
- template <typename IncomingValueType> |
- AddResult insertBefore(iterator it, IncomingValueType&& newValue) { |
- return m_impl.template add<NodeHashFunctions>( |
- std::forward<IncomingValueType>(newValue), it.getNode()); |
- } |
- |
- void erase(ValuePeekInType); |
- void erase(iterator); |
- void clear() { m_impl.clear(); } |
- template <typename Collection> |
- void removeAll(const Collection& other) { |
- WTF::removeAll(*this, other); |
- } |
- |
- template <typename VisitorDispatcher> |
- void trace(VisitorDispatcher visitor) { |
- m_impl.trace(visitor); |
- // Should the underlying table be moved by GC, register a callback |
- // that fixes up the interior pointers that the (Heap)LinkedHashSet keeps. |
- if (m_impl.m_table) { |
- Allocator::registerBackingStoreCallback( |
- visitor, m_impl.m_table, moveBackingCallback, |
- reinterpret_cast<void*>(&m_anchor)); |
- } |
- } |
- |
- int64_t modifications() const { return m_impl.modifications(); } |
- void checkModifications(int64_t mods) const { |
- m_impl.checkModifications(mods); |
- } |
- |
- private: |
- Node* anchor() { return reinterpret_cast<Node*>(&m_anchor); } |
- const Node* anchor() const { |
- return reinterpret_cast<const Node*>(&m_anchor); |
- } |
- Node* firstNode() { return reinterpret_cast<Node*>(m_anchor.m_next); } |
- const Node* firstNode() const { |
- return reinterpret_cast<const Node*>(m_anchor.m_next); |
- } |
- Node* lastNode() { return reinterpret_cast<Node*>(m_anchor.m_prev); } |
- const Node* lastNode() const { |
- return reinterpret_cast<const Node*>(m_anchor.m_prev); |
- } |
- |
- iterator makeIterator(const Node* position) { |
- return iterator(position, this); |
- } |
- const_iterator makeConstIterator(const Node* position) const { |
- return const_iterator(position, this); |
- } |
- reverse_iterator makeReverseIterator(const Node* position) { |
- return reverse_iterator(position, this); |
- } |
- const_reverse_iterator makeConstReverseIterator(const Node* position) const { |
- return const_reverse_iterator(position, this); |
- } |
- |
- static void moveBackingCallback(void* anchor, |
- void* from, |
- void* to, |
- size_t size) { |
- // Note: the hash table move may have been overlapping; linearly scan the |
- // entire table and fixup interior pointers into the old region with |
- // correspondingly offset ones into the new. |
- size_t tableSize = size / sizeof(Node); |
- Node* table = reinterpret_cast<Node*>(to); |
- NodeBase* fromStart = reinterpret_cast<NodeBase*>(from); |
- NodeBase* fromEnd = |
- reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(from) + size); |
- for (Node* element = table + tableSize - 1; element >= table; element--) { |
- Node& node = *element; |
- if (ImplType::isEmptyOrDeletedBucket(node)) |
- continue; |
- if (node.m_next >= fromStart && node.m_next < fromEnd) { |
- size_t diff = reinterpret_cast<uintptr_t>(node.m_next) - |
- reinterpret_cast<uintptr_t>(from); |
- node.m_next = |
- reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff); |
- } |
- if (node.m_prev >= fromStart && node.m_prev < fromEnd) { |
- size_t diff = reinterpret_cast<uintptr_t>(node.m_prev) - |
- reinterpret_cast<uintptr_t>(from); |
- node.m_prev = |
- reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff); |
- } |
- } |
- NodeBase* anchorNode = reinterpret_cast<NodeBase*>(anchor); |
- if (anchorNode->m_next >= fromStart && anchorNode->m_next < fromEnd) { |
- size_t diff = reinterpret_cast<uintptr_t>(anchorNode->m_next) - |
- reinterpret_cast<uintptr_t>(from); |
- anchorNode->m_next = |
- reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff); |
- } |
- if (anchorNode->m_prev >= fromStart && anchorNode->m_prev < fromEnd) { |
- size_t diff = reinterpret_cast<uintptr_t>(anchorNode->m_prev) - |
- reinterpret_cast<uintptr_t>(from); |
- anchorNode->m_prev = |
- reinterpret_cast<NodeBase*>(reinterpret_cast<uintptr_t>(to) + diff); |
- } |
- } |
- |
- ImplType m_impl; |
- NodeBase m_anchor; |
-}; |
- |
-template <typename Value, typename HashFunctions, typename Allocator> |
-struct LinkedHashSetTranslator { |
- STATIC_ONLY(LinkedHashSetTranslator); |
- typedef LinkedHashSetNode<Value, Allocator> Node; |
- typedef LinkedHashSetNodeBase NodeBase; |
- typedef typename HashTraits<Value>::PeekInType ValuePeekInType; |
- static unsigned hash(const Node& node) { |
- return HashFunctions::hash(node.m_value); |
- } |
- static unsigned hash(const ValuePeekInType& key) { |
- return HashFunctions::hash(key); |
- } |
- static bool equal(const Node& a, const ValuePeekInType& b) { |
- return HashFunctions::equal(a.m_value, b); |
- } |
- static bool equal(const Node& a, const Node& b) { |
- return HashFunctions::equal(a.m_value, b.m_value); |
- } |
- template <typename IncomingValueType> |
- static void translate(Node& location, |
- IncomingValueType&& key, |
- NodeBase* anchor) { |
- anchor->insertBefore(location); |
- location.m_value = std::forward<IncomingValueType>(key); |
- } |
- |
- // Empty (or deleted) slots have the m_next pointer set to null, but we |
- // don't do anything to the other fields, which may contain junk. |
- // Therefore you can't compare a newly constructed empty value with a |
- // slot and get the right answer. |
- static const bool safeToCompareToEmptyOrDeleted = false; |
-}; |
- |
-template <typename Value, typename Allocator> |
-struct LinkedHashSetExtractor { |
- STATIC_ONLY(LinkedHashSetExtractor); |
- static const Value& extract(const LinkedHashSetNode<Value, Allocator>& node) { |
- return node.m_value; |
- } |
-}; |
- |
-template <typename Value, typename ValueTraitsArg, typename Allocator> |
-struct LinkedHashSetTraits |
- : public SimpleClassHashTraits<LinkedHashSetNode<Value, Allocator>> { |
- STATIC_ONLY(LinkedHashSetTraits); |
- typedef LinkedHashSetNode<Value, Allocator> Node; |
- typedef ValueTraitsArg ValueTraits; |
- |
- // The slot is empty when the m_next field is zero so it's safe to zero |
- // the backing. |
- static const bool emptyValueIsZero = true; |
- |
- static const bool hasIsEmptyValueFunction = true; |
- static bool isEmptyValue(const Node& node) { return !node.m_next; } |
- |
- static const int deletedValue = -1; |
- |
- static void constructDeletedValue(Node& slot, bool) { |
- slot.m_next = reinterpret_cast<Node*>(deletedValue); |
- } |
- static bool isDeletedValue(const Node& slot) { |
- return slot.m_next == reinterpret_cast<Node*>(deletedValue); |
- } |
- |
- // Whether we need to trace and do weak processing depends on the traits of |
- // the type inside the node. |
- template <typename U = void> |
- struct IsTraceableInCollection { |
- STATIC_ONLY(IsTraceableInCollection); |
- static const bool value = |
- ValueTraits::template IsTraceableInCollection<>::value; |
- }; |
- static const WeakHandlingFlag weakHandlingFlag = |
- ValueTraits::weakHandlingFlag; |
-}; |
- |
-template <typename LinkedHashSetType> |
-class LinkedHashSetIterator { |
- DISALLOW_NEW(); |
- |
- private: |
- typedef typename LinkedHashSetType::Node Node; |
- typedef typename LinkedHashSetType::Traits Traits; |
- |
- typedef typename LinkedHashSetType::Value& ReferenceType; |
- typedef typename LinkedHashSetType::Value* PointerType; |
- |
- typedef LinkedHashSetConstIterator<LinkedHashSetType> const_iterator; |
- |
- Node* getNode() { return const_cast<Node*>(m_iterator.getNode()); } |
- |
- protected: |
- LinkedHashSetIterator(const Node* position, LinkedHashSetType* m_container) |
- : m_iterator(position, m_container) {} |
- |
- public: |
- // 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(); } |
- |
- LinkedHashSetIterator& operator++() { |
- ++m_iterator; |
- return *this; |
- } |
- LinkedHashSetIterator& operator--() { |
- --m_iterator; |
- return *this; |
- } |
- |
- // Postfix ++ and -- intentionally omitted. |
- |
- // Comparison. |
- bool operator==(const LinkedHashSetIterator& other) const { |
- return m_iterator == other.m_iterator; |
- } |
- bool operator!=(const LinkedHashSetIterator& other) const { |
- return m_iterator != other.m_iterator; |
- } |
- |
- operator const_iterator() const { return m_iterator; } |
- |
- protected: |
- const_iterator m_iterator; |
- template <typename T, typename U, typename V, typename W> |
- friend class LinkedHashSet; |
-}; |
- |
-template <typename LinkedHashSetType> |
-class LinkedHashSetConstIterator { |
- DISALLOW_NEW(); |
- |
- private: |
- typedef typename LinkedHashSetType::Node Node; |
- typedef typename LinkedHashSetType::Traits Traits; |
- |
- typedef const typename LinkedHashSetType::Value& ReferenceType; |
- typedef const typename LinkedHashSetType::Value* PointerType; |
- |
- const Node* getNode() const { return static_cast<const Node*>(m_position); } |
- |
- protected: |
- LinkedHashSetConstIterator(const LinkedHashSetNodeBase* position, |
- const LinkedHashSetType* container) |
- : m_position(position) |
-#if DCHECK_IS_ON() |
- , |
- m_container(container), |
- m_containerModifications(container->modifications()) |
-#endif |
- { |
- } |
- |
- public: |
- PointerType get() const { |
- checkModifications(); |
- return &static_cast<const Node*>(m_position)->m_value; |
- } |
- ReferenceType operator*() const { return *get(); } |
- PointerType operator->() const { return get(); } |
- |
- LinkedHashSetConstIterator& operator++() { |
- DCHECK(m_position); |
- checkModifications(); |
- m_position = m_position->m_next; |
- return *this; |
- } |
- |
- LinkedHashSetConstIterator& operator--() { |
- DCHECK(m_position); |
- checkModifications(); |
- m_position = m_position->m_prev; |
- return *this; |
- } |
- |
- // Postfix ++ and -- intentionally omitted. |
- |
- // Comparison. |
- bool operator==(const LinkedHashSetConstIterator& other) const { |
- return m_position == other.m_position; |
- } |
- bool operator!=(const LinkedHashSetConstIterator& other) const { |
- return m_position != other.m_position; |
- } |
- |
- private: |
- const LinkedHashSetNodeBase* m_position; |
-#if DCHECK_IS_ON() |
- void checkModifications() const { |
- m_container->checkModifications(m_containerModifications); |
- } |
- const LinkedHashSetType* m_container; |
- int64_t m_containerModifications; |
-#else |
- void checkModifications() const {} |
-#endif |
- template <typename T, typename U, typename V, typename W> |
- friend class LinkedHashSet; |
- friend class LinkedHashSetIterator<LinkedHashSetType>; |
-}; |
- |
-template <typename LinkedHashSetType> |
-class LinkedHashSetReverseIterator |
- : public LinkedHashSetIterator<LinkedHashSetType> { |
- typedef LinkedHashSetIterator<LinkedHashSetType> Superclass; |
- typedef LinkedHashSetConstReverseIterator<LinkedHashSetType> |
- const_reverse_iterator; |
- typedef typename LinkedHashSetType::Node Node; |
- |
- protected: |
- LinkedHashSetReverseIterator(const Node* position, |
- LinkedHashSetType* container) |
- : Superclass(position, container) {} |
- |
- public: |
- LinkedHashSetReverseIterator& operator++() { |
- Superclass::operator--(); |
- return *this; |
- } |
- LinkedHashSetReverseIterator& operator--() { |
- Superclass::operator++(); |
- return *this; |
- } |
- |
- // Postfix ++ and -- intentionally omitted. |
- |
- operator const_reverse_iterator() const { |
- return *reinterpret_cast<const_reverse_iterator*>(this); |
- } |
- |
- template <typename T, typename U, typename V, typename W> |
- friend class LinkedHashSet; |
-}; |
- |
-template <typename LinkedHashSetType> |
-class LinkedHashSetConstReverseIterator |
- : public LinkedHashSetConstIterator<LinkedHashSetType> { |
- typedef LinkedHashSetConstIterator<LinkedHashSetType> Superclass; |
- typedef typename LinkedHashSetType::Node Node; |
- |
- public: |
- LinkedHashSetConstReverseIterator(const Node* position, |
- const LinkedHashSetType* container) |
- : Superclass(position, container) {} |
- |
- LinkedHashSetConstReverseIterator& operator++() { |
- Superclass::operator--(); |
- return *this; |
- } |
- LinkedHashSetConstReverseIterator& operator--() { |
- Superclass::operator++(); |
- return *this; |
- } |
- |
- // Postfix ++ and -- intentionally omitted. |
- |
- template <typename T, typename U, typename V, typename W> |
- friend class LinkedHashSet; |
-}; |
- |
-template <typename T, typename U, typename V, typename Allocator> |
-inline LinkedHashSet<T, U, V, Allocator>::LinkedHashSet() { |
- static_assert( |
- Allocator::isGarbageCollected || |
- !IsPointerToGarbageCollectedType<T>::value, |
- "Cannot put raw pointers to garbage-collected classes into " |
- "an off-heap LinkedHashSet. Use HeapLinkedHashSet<Member<T>> instead."); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline LinkedHashSet<T, U, V, W>::LinkedHashSet(const LinkedHashSet& other) |
- : m_anchor() { |
- const_iterator end = other.end(); |
- for (const_iterator it = other.begin(); it != end; ++it) |
- insert(*it); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline LinkedHashSet<T, U, V, W>::LinkedHashSet(LinkedHashSet&& other) |
- : m_anchor() { |
- swap(other); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=( |
- const LinkedHashSet& other) { |
- LinkedHashSet tmp(other); |
- swap(tmp); |
- return *this; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=( |
- LinkedHashSet&& other) { |
- swap(other); |
- return *this; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline void LinkedHashSet<T, U, V, W>::swap(LinkedHashSet& other) { |
- m_impl.swap(other.m_impl); |
- swapAnchor(m_anchor, other.m_anchor); |
-} |
- |
-template <typename T, typename U, typename V, typename Allocator> |
-inline LinkedHashSet<T, U, V, Allocator>::~LinkedHashSet() { |
- // The destructor of m_anchor will implicitly be called here, which will |
- // unlink the anchor from the collection. |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline T& LinkedHashSet<T, U, V, W>::front() { |
- DCHECK(!isEmpty()); |
- return firstNode()->m_value; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline const T& LinkedHashSet<T, U, V, W>::front() const { |
- DCHECK(!isEmpty()); |
- return firstNode()->m_value; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline void LinkedHashSet<T, U, V, W>::removeFirst() { |
- DCHECK(!isEmpty()); |
- m_impl.remove(static_cast<Node*>(m_anchor.m_next)); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline T& LinkedHashSet<T, U, V, W>::back() { |
- DCHECK(!isEmpty()); |
- return lastNode()->m_value; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline const T& LinkedHashSet<T, U, V, W>::back() const { |
- DCHECK(!isEmpty()); |
- return lastNode()->m_value; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline void LinkedHashSet<T, U, V, W>::pop_back() { |
- DCHECK(!isEmpty()); |
- m_impl.remove(static_cast<Node*>(m_anchor.m_prev)); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline typename LinkedHashSet<T, U, V, W>::iterator |
-LinkedHashSet<T, U, V, W>::find(ValuePeekInType value) { |
- LinkedHashSet::Node* node = |
- m_impl.template lookup<LinkedHashSet::NodeHashFunctions, ValuePeekInType>( |
- value); |
- if (!node) |
- return end(); |
- return makeIterator(node); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline typename LinkedHashSet<T, U, V, W>::const_iterator |
-LinkedHashSet<T, U, V, W>::find(ValuePeekInType value) const { |
- const LinkedHashSet::Node* node = |
- m_impl.template lookup<LinkedHashSet::NodeHashFunctions, ValuePeekInType>( |
- value); |
- if (!node) |
- return end(); |
- return makeConstIterator(node); |
-} |
- |
-template <typename Translator> |
-struct LinkedHashSetTranslatorAdapter { |
- STATIC_ONLY(LinkedHashSetTranslatorAdapter); |
- 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 Value, typename U, typename V, typename W> |
-template <typename HashTranslator, typename T> |
-inline typename LinkedHashSet<Value, U, V, W>::iterator |
-LinkedHashSet<Value, U, V, W>::find(const T& value) { |
- typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions; |
- const LinkedHashSet::Node* node = |
- m_impl.template lookup<TranslatedFunctions, const T&>(value); |
- if (!node) |
- return end(); |
- return makeIterator(node); |
-} |
- |
-template <typename Value, typename U, typename V, typename W> |
-template <typename HashTranslator, typename T> |
-inline typename LinkedHashSet<Value, U, V, W>::const_iterator |
-LinkedHashSet<Value, U, V, W>::find(const T& value) const { |
- typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions; |
- const LinkedHashSet::Node* node = |
- m_impl.template lookup<TranslatedFunctions, const T&>(value); |
- if (!node) |
- return end(); |
- return makeConstIterator(node); |
-} |
- |
-template <typename Value, typename U, typename V, typename W> |
-template <typename HashTranslator, typename T> |
-inline bool LinkedHashSet<Value, U, V, W>::contains(const T& value) const { |
- return m_impl |
- .template contains<LinkedHashSetTranslatorAdapter<HashTranslator>>(value); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline bool LinkedHashSet<T, U, V, W>::contains(ValuePeekInType value) const { |
- return m_impl.template contains<NodeHashFunctions>(value); |
-} |
- |
-template <typename Value, |
- typename HashFunctions, |
- typename Traits, |
- typename Allocator> |
-template <typename IncomingValueType> |
-typename LinkedHashSet<Value, HashFunctions, Traits, Allocator>::AddResult |
-LinkedHashSet<Value, HashFunctions, Traits, Allocator>::insert( |
- IncomingValueType&& value) { |
- return m_impl.template add<NodeHashFunctions>( |
- std::forward<IncomingValueType>(value), &m_anchor); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-template <typename IncomingValueType> |
-typename LinkedHashSet<T, U, V, W>::iterator |
-LinkedHashSet<T, U, V, W>::addReturnIterator(IncomingValueType&& value) { |
- typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>( |
- std::forward<IncomingValueType>(value), &m_anchor); |
- return makeIterator(result.storedValue); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-template <typename IncomingValueType> |
-typename LinkedHashSet<T, U, V, W>::AddResult |
-LinkedHashSet<T, U, V, W>::appendOrMoveToLast(IncomingValueType&& value) { |
- typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>( |
- std::forward<IncomingValueType>(value), &m_anchor); |
- Node* node = result.storedValue; |
- if (!result.isNewEntry) { |
- node->unlink(); |
- m_anchor.insertBefore(*node); |
- } |
- return result; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-template <typename IncomingValueType> |
-typename LinkedHashSet<T, U, V, W>::AddResult |
-LinkedHashSet<T, U, V, W>::prependOrMoveToFirst(IncomingValueType&& value) { |
- typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>( |
- std::forward<IncomingValueType>(value), m_anchor.m_next); |
- Node* node = result.storedValue; |
- if (!result.isNewEntry) { |
- node->unlink(); |
- m_anchor.insertAfter(*node); |
- } |
- return result; |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-template <typename IncomingValueType> |
-typename LinkedHashSet<T, U, V, W>::AddResult |
-LinkedHashSet<T, U, V, W>::insertBefore(ValuePeekInType beforeValue, |
- IncomingValueType&& newValue) { |
- return insertBefore(find(beforeValue), |
- std::forward<IncomingValueType>(newValue)); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline void LinkedHashSet<T, U, V, W>::erase(iterator it) { |
- if (it == end()) |
- return; |
- m_impl.remove(it.getNode()); |
-} |
- |
-template <typename T, typename U, typename V, typename W> |
-inline void LinkedHashSet<T, U, V, W>::erase(ValuePeekInType value) { |
- erase(find(value)); |
-} |
- |
-inline void swapAnchor(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b) { |
- DCHECK(a.m_prev); |
- DCHECK(a.m_next); |
- DCHECK(b.m_prev); |
- DCHECK(b.m_next); |
- swap(a.m_prev, b.m_prev); |
- swap(a.m_next, b.m_next); |
- if (b.m_next == &a) { |
- DCHECK_EQ(b.m_prev, &a); |
- b.m_next = &b; |
- b.m_prev = &b; |
- } else { |
- b.m_next->m_prev = &b; |
- b.m_prev->m_next = &b; |
- } |
- if (a.m_next == &b) { |
- DCHECK_EQ(a.m_prev, &b); |
- a.m_next = &a; |
- a.m_prev = &a; |
- } else { |
- a.m_next->m_prev = &a; |
- a.m_prev->m_next = &a; |
- } |
-} |
- |
-inline void swap(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b) { |
- DCHECK_NE(a.m_next, &a); |
- DCHECK_NE(b.m_next, &b); |
- swap(a.m_prev, b.m_prev); |
- swap(a.m_next, b.m_next); |
- if (b.m_next) { |
- b.m_next->m_prev = &b; |
- b.m_prev->m_next = &b; |
- } |
- if (a.m_next) { |
- a.m_next->m_prev = &a; |
- a.m_prev->m_next = &a; |
- } |
-} |
- |
-template <typename T, typename Allocator> |
-inline void swap(LinkedHashSetNode<T, Allocator>& a, |
- LinkedHashSetNode<T, Allocator>& b) { |
- typedef LinkedHashSetNodeBase Base; |
- // The key and value cannot be swapped atomically, and it would be |
- // wrong to have a GC when only one was swapped and the other still |
- // contained garbage (eg. from a previous use of the same slot). |
- // Therefore we forbid a GC until both the key and the value are |
- // swapped. |
- Allocator::enterGCForbiddenScope(); |
- swap(static_cast<Base&>(a), static_cast<Base&>(b)); |
- swap(a.m_value, b.m_value); |
- Allocator::leaveGCForbiddenScope(); |
-} |
- |
-} // namespace WTF |
- |
-using WTF::LinkedHashSet; |
- |
-#endif /* WTF_LinkedHashSet_h */ |
+// The contents of this header was moved to platform/wtf as part of |
+// WTF migration project. See the following post for details: |
+// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ |