| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv
ed. |
| 3 * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com> | 3 * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com> |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 | 32 |
| 33 // LinkedHashSet: Just like HashSet, this class provides a Set | 33 // LinkedHashSet: Just like HashSet, this class provides a Set |
| 34 // interface - a collection of unique objects with O(1) insertion, | 34 // interface - a collection of unique objects with O(1) insertion, |
| 35 // removal and test for containership. However, it also has an | 35 // removal and test for containership. However, it also has an |
| 36 // order - iterating it will always give back values in the order | 36 // order - iterating it will always give back values in the order |
| 37 // in which they are added. | 37 // in which they are added. |
| 38 | 38 |
| 39 // Unlike ListHashSet, but like most WTF collections, iteration is NOT safe | 39 // Unlike ListHashSet, but like most WTF collections, iteration is NOT safe |
| 40 // against mutation of the LinkedHashSet. | 40 // against mutation of the LinkedHashSet. |
| 41 | 41 |
| 42 template<typename Value, typename HashFunctions, typename HashTraits, typename A
llocator> class LinkedHashSet; | 42 template <typename Value, typename HashFunctions, typename HashTraits, typename
Allocator> |
| 43 | 43 class LinkedHashSet; |
| 44 template<typename LinkedHashSet> class LinkedHashSetIterator; | 44 |
| 45 template<typename LinkedHashSet> class LinkedHashSetConstIterator; | 45 template <typename LinkedHashSet> |
| 46 template<typename LinkedHashSet> class LinkedHashSetReverseIterator; | 46 class LinkedHashSetIterator; |
| 47 template<typename LinkedHashSet> class LinkedHashSetConstReverseIterator; | 47 template <typename LinkedHashSet> |
| 48 | 48 class LinkedHashSetConstIterator; |
| 49 template<typename Value, typename HashFunctions, typename Allocator> struct Link
edHashSetTranslator; | 49 template <typename LinkedHashSet> |
| 50 template<typename Value, typename Allocator> struct LinkedHashSetExtractor; | 50 class LinkedHashSetReverseIterator; |
| 51 template<typename Value, typename ValueTraits, typename Allocator> struct Linked
HashSetTraits; | 51 template <typename LinkedHashSet> |
| 52 class LinkedHashSetConstReverseIterator; |
| 53 |
| 54 template <typename Value, typename HashFunctions, typename Allocator> |
| 55 struct LinkedHashSetTranslator; |
| 56 template <typename Value, typename Allocator> |
| 57 struct LinkedHashSetExtractor; |
| 58 template <typename Value, typename ValueTraits, typename Allocator> |
| 59 struct LinkedHashSetTraits; |
| 52 | 60 |
| 53 class LinkedHashSetNodeBase { | 61 class LinkedHashSetNodeBase { |
| 54 public: | 62 public: |
| 55 LinkedHashSetNodeBase() : m_prev(this), m_next(this) { } | 63 LinkedHashSetNodeBase() |
| 56 | 64 : m_prev(this), m_next(this) {} |
| 57 NO_LAZY_SWEEP_SANITIZE_ADDRESS | 65 |
| 58 void unlink() | 66 NO_LAZY_SWEEP_SANITIZE_ADDRESS |
| 59 { | 67 void unlink() { |
| 60 if (!m_next) | 68 if (!m_next) |
| 61 return; | 69 return; |
| 62 ASSERT(m_prev); | 70 ASSERT(m_prev); |
| 63 ASSERT(m_next->m_prev == this); | 71 ASSERT(m_next->m_prev == this); |
| 64 ASSERT(m_prev->m_next == this); | 72 ASSERT(m_prev->m_next == this); |
| 65 m_next->m_prev = m_prev; | 73 m_next->m_prev = m_prev; |
| 66 m_prev->m_next = m_next; | 74 m_prev->m_next = m_next; |
| 67 } | 75 } |
| 68 | 76 |
| 69 ~LinkedHashSetNodeBase() | 77 ~LinkedHashSetNodeBase() { |
| 70 { | 78 unlink(); |
| 71 unlink(); | 79 } |
| 72 } | 80 |
| 73 | 81 void insertBefore(LinkedHashSetNodeBase& other) { |
| 74 void insertBefore(LinkedHashSetNodeBase& other) | 82 other.m_next = this; |
| 75 { | 83 other.m_prev = m_prev; |
| 76 other.m_next = this; | 84 m_prev->m_next = &other; |
| 77 other.m_prev = m_prev; | 85 m_prev = &other; |
| 78 m_prev->m_next = &other; | 86 ASSERT(other.m_next); |
| 79 m_prev = &other; | 87 ASSERT(other.m_prev); |
| 80 ASSERT(other.m_next); | 88 ASSERT(m_next); |
| 81 ASSERT(other.m_prev); | 89 ASSERT(m_prev); |
| 82 ASSERT(m_next); | 90 } |
| 83 ASSERT(m_prev); | 91 |
| 84 } | 92 void insertAfter(LinkedHashSetNodeBase& other) { |
| 85 | 93 other.m_prev = this; |
| 86 void insertAfter(LinkedHashSetNodeBase& other) | 94 other.m_next = m_next; |
| 87 { | 95 m_next->m_prev = &other; |
| 88 other.m_prev = this; | 96 m_next = &other; |
| 89 other.m_next = m_next; | 97 ASSERT(other.m_next); |
| 90 m_next->m_prev = &other; | 98 ASSERT(other.m_prev); |
| 91 m_next = &other; | 99 ASSERT(m_next); |
| 92 ASSERT(other.m_next); | 100 ASSERT(m_prev); |
| 93 ASSERT(other.m_prev); | 101 } |
| 94 ASSERT(m_next); | 102 |
| 95 ASSERT(m_prev); | 103 LinkedHashSetNodeBase(LinkedHashSetNodeBase* prev, LinkedHashSetNodeBase* next
) |
| 96 } | 104 : m_prev(prev), m_next(next) { |
| 97 | 105 ASSERT((prev && next) || (!prev && !next)); |
| 98 LinkedHashSetNodeBase(LinkedHashSetNodeBase* prev, LinkedHashSetNodeBase* ne
xt) | 106 } |
| 99 : m_prev(prev) | 107 |
| 100 , m_next(next) | 108 LinkedHashSetNodeBase* m_prev; |
| 101 { | 109 LinkedHashSetNodeBase* m_next; |
| 102 ASSERT((prev && next) || (!prev && !next)); | 110 |
| 103 } | 111 protected: |
| 104 | 112 // If we take a copy of a node we can't copy the next and prev pointers, |
| 105 LinkedHashSetNodeBase* m_prev; | 113 // since they point to something that does not point at us. This is used |
| 106 LinkedHashSetNodeBase* m_next; | 114 // inside the shouldExpand() "if" in HashTable::add. |
| 107 | 115 LinkedHashSetNodeBase(const LinkedHashSetNodeBase& other) |
| 108 protected: | 116 : m_prev(0), m_next(0) {} |
| 109 // If we take a copy of a node we can't copy the next and prev pointers, | 117 |
| 110 // since they point to something that does not point at us. This is used | 118 private: |
| 111 // inside the shouldExpand() "if" in HashTable::add. | 119 // Should not be used. |
| 112 LinkedHashSetNodeBase(const LinkedHashSetNodeBase& other) | 120 LinkedHashSetNodeBase& operator=(const LinkedHashSetNodeBase& other); |
| 113 : m_prev(0) | 121 }; |
| 114 , m_next(0) { } | 122 |
| 115 | 123 template <typename ValueArg, typename Allocator> |
| 116 private: | |
| 117 // Should not be used. | |
| 118 LinkedHashSetNodeBase& operator=(const LinkedHashSetNodeBase& other); | |
| 119 }; | |
| 120 | |
| 121 template<typename ValueArg, typename Allocator> | |
| 122 class LinkedHashSetNode : public LinkedHashSetNodeBase { | 124 class LinkedHashSetNode : public LinkedHashSetNodeBase { |
| 123 public: | 125 public: |
| 124 LinkedHashSetNode(const ValueArg& value, LinkedHashSetNodeBase* prev, Linked
HashSetNodeBase* next) | 126 LinkedHashSetNode(const ValueArg& value, LinkedHashSetNodeBase* prev, LinkedHa
shSetNodeBase* next) |
| 125 : LinkedHashSetNodeBase(prev, next) | 127 : LinkedHashSetNodeBase(prev, next), m_value(value) { |
| 126 , m_value(value) | 128 } |
| 127 { | 129 |
| 128 } | 130 ValueArg m_value; |
| 129 | 131 |
| 130 ValueArg m_value; | 132 private: |
| 131 | 133 // Not used. |
| 132 private: | 134 LinkedHashSetNode(const LinkedHashSetNode&); |
| 133 // Not used. | 135 }; |
| 134 LinkedHashSetNode(const LinkedHashSetNode&); | 136 |
| 135 }; | 137 template < |
| 136 | |
| 137 template< | |
| 138 typename ValueArg, | 138 typename ValueArg, |
| 139 typename HashFunctions = typename DefaultHash<ValueArg>::Hash, | 139 typename HashFunctions = typename DefaultHash<ValueArg>::Hash, |
| 140 typename TraitsArg = HashTraits<ValueArg>, | 140 typename TraitsArg = HashTraits<ValueArg>, |
| 141 typename Allocator = PartitionAllocator> | 141 typename Allocator = PartitionAllocator> |
| 142 class LinkedHashSet { | 142 class LinkedHashSet { |
| 143 WTF_USE_ALLOCATOR(LinkedHashSet, Allocator); | 143 WTF_USE_ALLOCATOR(LinkedHashSet, Allocator); |
| 144 private: | 144 |
| 145 typedef ValueArg Value; | 145 private: |
| 146 typedef TraitsArg Traits; | 146 typedef ValueArg Value; |
| 147 typedef LinkedHashSetNode<Value, Allocator> Node; | 147 typedef TraitsArg Traits; |
| 148 typedef LinkedHashSetNodeBase NodeBase; | 148 typedef LinkedHashSetNode<Value, Allocator> Node; |
| 149 typedef LinkedHashSetTranslator<Value, HashFunctions, Allocator> NodeHashFun
ctions; | 149 typedef LinkedHashSetNodeBase NodeBase; |
| 150 typedef LinkedHashSetTraits<Value, Traits, Allocator> NodeHashTraits; | 150 typedef LinkedHashSetTranslator<Value, HashFunctions, Allocator> NodeHashFunct
ions; |
| 151 | 151 typedef LinkedHashSetTraits<Value, Traits, Allocator> NodeHashTraits; |
| 152 typedef HashTable<Node, Node, IdentityExtractor, | 152 |
| 153 NodeHashFunctions, NodeHashTraits, NodeHashTraits, Allocator> ImplType; | 153 typedef HashTable<Node, Node, IdentityExtractor, NodeHashFunctions, NodeHashTr
aits, NodeHashTraits, Allocator> ImplType; |
| 154 | 154 |
| 155 public: | 155 public: |
| 156 typedef LinkedHashSetIterator<LinkedHashSet> iterator; | 156 typedef LinkedHashSetIterator<LinkedHashSet> iterator; |
| 157 friend class LinkedHashSetIterator<LinkedHashSet>; | 157 friend class LinkedHashSetIterator<LinkedHashSet>; |
| 158 typedef LinkedHashSetConstIterator<LinkedHashSet> const_iterator; | 158 typedef LinkedHashSetConstIterator<LinkedHashSet> const_iterator; |
| 159 friend class LinkedHashSetConstIterator<LinkedHashSet>; | 159 friend class LinkedHashSetConstIterator<LinkedHashSet>; |
| 160 | 160 |
| 161 typedef LinkedHashSetReverseIterator<LinkedHashSet> reverse_iterator; | 161 typedef LinkedHashSetReverseIterator<LinkedHashSet> reverse_iterator; |
| 162 friend class LinkedHashSetReverseIterator<LinkedHashSet>; | 162 friend class LinkedHashSetReverseIterator<LinkedHashSet>; |
| 163 typedef LinkedHashSetConstReverseIterator<LinkedHashSet> const_reverse_itera
tor; | 163 typedef LinkedHashSetConstReverseIterator<LinkedHashSet> const_reverse_iterato
r; |
| 164 friend class LinkedHashSetConstReverseIterator<LinkedHashSet>; | 164 friend class LinkedHashSetConstReverseIterator<LinkedHashSet>; |
| 165 | 165 |
| 166 struct AddResult { | 166 struct AddResult { |
| 167 AddResult(const typename ImplType::AddResult& hashTableAddResult) | 167 AddResult(const typename ImplType::AddResult& hashTableAddResult) |
| 168 : storedValue(&hashTableAddResult.storedValue->m_value) | 168 : storedValue(&hashTableAddResult.storedValue->m_value), isNewEntry(hash
TableAddResult.isNewEntry) { |
| 169 , isNewEntry(hashTableAddResult.isNewEntry) | 169 } |
| 170 { | 170 |
| 171 } | 171 Value* storedValue; |
| 172 | 172 bool isNewEntry; |
| 173 Value* storedValue; | 173 }; |
| 174 bool isNewEntry; | 174 |
| 175 }; | 175 typedef typename HashTraits<Value>::PeekInType ValuePeekInType; |
| 176 | 176 |
| 177 typedef typename HashTraits<Value>::PeekInType ValuePeekInType; | 177 LinkedHashSet(); |
| 178 | 178 LinkedHashSet(const LinkedHashSet&); |
| 179 LinkedHashSet(); | 179 LinkedHashSet& operator=(const LinkedHashSet&); |
| 180 LinkedHashSet(const LinkedHashSet&); | 180 |
| 181 LinkedHashSet& operator=(const LinkedHashSet&); | 181 // Needs finalization. The anchor needs to unlink itself from the chain. |
| 182 | 182 ~LinkedHashSet(); |
| 183 // Needs finalization. The anchor needs to unlink itself from the chain. | 183 |
| 184 ~LinkedHashSet(); | 184 static void finalize(void* pointer) { reinterpret_cast<LinkedHashSet*>(pointer
)->~LinkedHashSet(); } |
| 185 | 185 void finalizeGarbageCollectedObject() { finalize(this); } |
| 186 static void finalize(void* pointer) { reinterpret_cast<LinkedHashSet*>(point
er)->~LinkedHashSet(); } | 186 |
| 187 void finalizeGarbageCollectedObject() { finalize(this); } | 187 void swap(LinkedHashSet&); |
| 188 | 188 |
| 189 void swap(LinkedHashSet&); | 189 unsigned size() const { return m_impl.size(); } |
| 190 | 190 unsigned capacity() const { return m_impl.capacity(); } |
| 191 unsigned size() const { return m_impl.size(); } | 191 bool isEmpty() const { return m_impl.isEmpty(); } |
| 192 unsigned capacity() const { return m_impl.capacity(); } | 192 |
| 193 bool isEmpty() const { return m_impl.isEmpty(); } | 193 iterator begin() { return makeIterator(firstNode()); } |
| 194 | 194 iterator end() { return makeIterator(anchor()); } |
| 195 iterator begin() { return makeIterator(firstNode()); } | 195 const_iterator begin() const { return makeConstIterator(firstNode()); } |
| 196 iterator end() { return makeIterator(anchor()); } | 196 const_iterator end() const { return makeConstIterator(anchor()); } |
| 197 const_iterator begin() const { return makeConstIterator(firstNode()); } | 197 |
| 198 const_iterator end() const { return makeConstIterator(anchor()); } | 198 reverse_iterator rbegin() { return makeReverseIterator(lastNode()); } |
| 199 | 199 reverse_iterator rend() { return makeReverseIterator(anchor()); } |
| 200 reverse_iterator rbegin() { return makeReverseIterator(lastNode()); } | 200 const_reverse_iterator rbegin() const { return makeConstReverseIterator(lastNo
de()); } |
| 201 reverse_iterator rend() { return makeReverseIterator(anchor()); } | 201 const_reverse_iterator rend() const { return makeConstReverseIterator(anchor()
); } |
| 202 const_reverse_iterator rbegin() const { return makeConstReverseIterator(last
Node()); } | 202 |
| 203 const_reverse_iterator rend() const { return makeConstReverseIterator(anchor
()); } | 203 Value& first(); |
| 204 | 204 const Value& first() const; |
| 205 Value& first(); | 205 void removeFirst(); |
| 206 const Value& first() const; | 206 |
| 207 void removeFirst(); | 207 Value& last(); |
| 208 | 208 const Value& last() const; |
| 209 Value& last(); | 209 void removeLast(); |
| 210 const Value& last() const; | 210 |
| 211 void removeLast(); | 211 iterator find(ValuePeekInType); |
| 212 | 212 const_iterator find(ValuePeekInType) const; |
| 213 iterator find(ValuePeekInType); | 213 bool contains(ValuePeekInType) const; |
| 214 const_iterator find(ValuePeekInType) const; | 214 |
| 215 bool contains(ValuePeekInType) const; | 215 // An alternate version of find() that finds the object by hashing and compari
ng |
| 216 | 216 // with some other type, to avoid the cost of type conversion. |
| 217 // An alternate version of find() that finds the object by hashing and compa
ring | 217 // The HashTranslator interface is defined in HashSet. |
| 218 // with some other type, to avoid the cost of type conversion. | 218 template <typename HashTranslator, typename T> |
| 219 // The HashTranslator interface is defined in HashSet. | 219 iterator find(const T&); |
| 220 template<typename HashTranslator, typename T> iterator find(const T&); | 220 template <typename HashTranslator, typename T> |
| 221 template<typename HashTranslator, typename T> const_iterator find(const T&)
const; | 221 const_iterator find(const T&) const; |
| 222 template<typename HashTranslator, typename T> bool contains(const T&) const; | 222 template <typename HashTranslator, typename T> |
| 223 | 223 bool contains(const T&) const; |
| 224 // The return value of add is a pair of a pointer to the stored value, | 224 |
| 225 // and a bool that is true if an new entry was added. | 225 // The return value of add is a pair of a pointer to the stored value, |
| 226 AddResult add(ValuePeekInType); | 226 // and a bool that is true if an new entry was added. |
| 227 | 227 AddResult add(ValuePeekInType); |
| 228 // Same as add() except that the return value is an | 228 |
| 229 // iterator. Useful in cases where it's needed to have the | 229 // Same as add() except that the return value is an |
| 230 // same return value as find() and where it's not possible to | 230 // iterator. Useful in cases where it's needed to have the |
| 231 // use a pointer to the storedValue. | 231 // same return value as find() and where it's not possible to |
| 232 iterator addReturnIterator(ValuePeekInType); | 232 // use a pointer to the storedValue. |
| 233 | 233 iterator addReturnIterator(ValuePeekInType); |
| 234 // Add the value to the end of the collection. If the value was already in | 234 |
| 235 // the list, it is moved to the end. | 235 // Add the value to the end of the collection. If the value was already in |
| 236 AddResult appendOrMoveToLast(ValuePeekInType); | 236 // the list, it is moved to the end. |
| 237 | 237 AddResult appendOrMoveToLast(ValuePeekInType); |
| 238 // Add the value to the beginning of the collection. If the value was alread
y in | 238 |
| 239 // the list, it is moved to the beginning. | 239 // Add the value to the beginning of the collection. If the value was already
in |
| 240 AddResult prependOrMoveToFirst(ValuePeekInType); | 240 // the list, it is moved to the beginning. |
| 241 | 241 AddResult prependOrMoveToFirst(ValuePeekInType); |
| 242 AddResult insertBefore(ValuePeekInType beforeValue, ValuePeekInType newValue
); | 242 |
| 243 AddResult insertBefore(iterator it, ValuePeekInType newValue) { return m_imp
l.template add<NodeHashFunctions>(newValue, it.node()); } | 243 AddResult insertBefore(ValuePeekInType beforeValue, ValuePeekInType newValue); |
| 244 | 244 AddResult insertBefore(iterator it, ValuePeekInType newValue) { return m_impl.
template add<NodeHashFunctions>(newValue, it.node()); } |
| 245 void remove(ValuePeekInType); | 245 |
| 246 void remove(iterator); | 246 void remove(ValuePeekInType); |
| 247 void clear() { m_impl.clear(); } | 247 void remove(iterator); |
| 248 template<typename Collection> | 248 void clear() { m_impl.clear(); } |
| 249 void removeAll(const Collection& other) { WTF::removeAll(*this, other); } | 249 template <typename Collection> |
| 250 | 250 void removeAll(const Collection& other) { WTF::removeAll(*this, other); } |
| 251 template<typename VisitorDispatcher> | 251 |
| 252 void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); } | 252 template <typename VisitorDispatcher> |
| 253 | 253 void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); } |
| 254 int64_t modifications() const { return m_impl.modifications(); } | 254 |
| 255 void checkModifications(int64_t mods) const { m_impl.checkModifications(mods
); } | 255 int64_t modifications() const { return m_impl.modifications(); } |
| 256 | 256 void checkModifications(int64_t mods) const { m_impl.checkModifications(mods);
} |
| 257 private: | 257 |
| 258 Node* anchor() { return reinterpret_cast<Node*>(&m_anchor); } | 258 private: |
| 259 const Node* anchor() const { return reinterpret_cast<const Node*>(&m_anchor)
; } | 259 Node* anchor() { return reinterpret_cast<Node*>(&m_anchor); } |
| 260 Node* firstNode() { return reinterpret_cast<Node*>(m_anchor.m_next); } | 260 const Node* anchor() const { return reinterpret_cast<const Node*>(&m_anchor);
} |
| 261 const Node* firstNode() const { return reinterpret_cast<const Node*>(m_ancho
r.m_next); } | 261 Node* firstNode() { return reinterpret_cast<Node*>(m_anchor.m_next); } |
| 262 Node* lastNode() { return reinterpret_cast<Node*>(m_anchor.m_prev); } | 262 const Node* firstNode() const { return reinterpret_cast<const Node*>(m_anchor.
m_next); } |
| 263 const Node* lastNode() const { return reinterpret_cast<const Node*>(m_anchor
.m_prev); } | 263 Node* lastNode() { return reinterpret_cast<Node*>(m_anchor.m_prev); } |
| 264 | 264 const Node* lastNode() const { return reinterpret_cast<const Node*>(m_anchor.m
_prev); } |
| 265 iterator makeIterator(const Node* position) { return iterator(position, this
); } | 265 |
| 266 const_iterator makeConstIterator(const Node* position) const { return const_
iterator(position, this); } | 266 iterator makeIterator(const Node* position) { return iterator(position, this);
} |
| 267 reverse_iterator makeReverseIterator(const Node* position) { return reverse_
iterator(position, this); } | 267 const_iterator makeConstIterator(const Node* position) const { return const_it
erator(position, this); } |
| 268 const_reverse_iterator makeConstReverseIterator(const Node* position) const
{ return const_reverse_iterator(position, this); } | 268 reverse_iterator makeReverseIterator(const Node* position) { return reverse_it
erator(position, this); } |
| 269 | 269 const_reverse_iterator makeConstReverseIterator(const Node* position) const {
return const_reverse_iterator(position, this); } |
| 270 ImplType m_impl; | 270 |
| 271 NodeBase m_anchor; | 271 ImplType m_impl; |
| 272 }; | 272 NodeBase m_anchor; |
| 273 | 273 }; |
| 274 template<typename Value, typename HashFunctions, typename Allocator> | 274 |
| 275 template <typename Value, typename HashFunctions, typename Allocator> |
| 275 struct LinkedHashSetTranslator { | 276 struct LinkedHashSetTranslator { |
| 276 typedef LinkedHashSetNode<Value, Allocator> Node; | 277 typedef LinkedHashSetNode<Value, Allocator> Node; |
| 277 typedef LinkedHashSetNodeBase NodeBase; | 278 typedef LinkedHashSetNodeBase NodeBase; |
| 278 typedef typename HashTraits<Value>::PeekInType ValuePeekInType; | 279 typedef typename HashTraits<Value>::PeekInType ValuePeekInType; |
| 279 static unsigned hash(const Node& node) { return HashFunctions::hash(node.m_v
alue); } | 280 static unsigned hash(const Node& node) { return HashFunctions::hash(node.m_val
ue); } |
| 280 static unsigned hash(const ValuePeekInType& key) { return HashFunctions::has
h(key); } | 281 static unsigned hash(const ValuePeekInType& key) { return HashFunctions::hash(
key); } |
| 281 static bool equal(const Node& a, const ValuePeekInType& b) { return HashFunc
tions::equal(a.m_value, b); } | 282 static bool equal(const Node& a, const ValuePeekInType& b) { return HashFuncti
ons::equal(a.m_value, b); } |
| 282 static bool equal(const Node& a, const Node& b) { return HashFunctions::equa
l(a.m_value, b.m_value); } | 283 static bool equal(const Node& a, const Node& b) { return HashFunctions::equal(
a.m_value, b.m_value); } |
| 283 static void translate(Node& location, ValuePeekInType key, NodeBase* anchor) | 284 static void translate(Node& location, ValuePeekInType key, NodeBase* anchor) { |
| 284 { | 285 anchor->insertBefore(location); |
| 285 anchor->insertBefore(location); | 286 location.m_value = key; |
| 286 location.m_value = key; | 287 } |
| 287 } | 288 |
| 288 | 289 // Empty (or deleted) slots have the m_next pointer set to null, but we |
| 289 // Empty (or deleted) slots have the m_next pointer set to null, but we | 290 // don't do anything to the other fields, which may contain junk. |
| 290 // don't do anything to the other fields, which may contain junk. | 291 // Therefore you can't compare a newly constructed empty value with a |
| 291 // Therefore you can't compare a newly constructed empty value with a | 292 // slot and get the right answer. |
| 292 // slot and get the right answer. | 293 static const bool safeToCompareToEmptyOrDeleted = false; |
| 293 static const bool safeToCompareToEmptyOrDeleted = false; | 294 }; |
| 294 }; | 295 |
| 295 | 296 template <typename Value, typename Allocator> |
| 296 template<typename Value, typename Allocator> | |
| 297 struct LinkedHashSetExtractor { | 297 struct LinkedHashSetExtractor { |
| 298 static const Value& extract(const LinkedHashSetNode<Value, Allocator>& node)
{ return node.m_value; } | 298 static const Value& extract(const LinkedHashSetNode<Value, Allocator>& node) {
return node.m_value; } |
| 299 }; | 299 }; |
| 300 | 300 |
| 301 template<typename Value, typename ValueTraitsArg, typename Allocator> | 301 template <typename Value, typename ValueTraitsArg, typename Allocator> |
| 302 struct LinkedHashSetTraits : public SimpleClassHashTraits<LinkedHashSetNode<Valu
e, Allocator>> { | 302 struct LinkedHashSetTraits : public SimpleClassHashTraits<LinkedHashSetNode<Valu
e, Allocator>> { |
| 303 typedef LinkedHashSetNode<Value, Allocator> Node; | 303 typedef LinkedHashSetNode<Value, Allocator> Node; |
| 304 typedef ValueTraitsArg ValueTraits; | 304 typedef ValueTraitsArg ValueTraits; |
| 305 | 305 |
| 306 // The slot is empty when the m_next field is zero so it's safe to zero | 306 // The slot is empty when the m_next field is zero so it's safe to zero |
| 307 // the backing. | 307 // the backing. |
| 308 static const bool emptyValueIsZero = true; | 308 static const bool emptyValueIsZero = true; |
| 309 | 309 |
| 310 static const bool hasIsEmptyValueFunction = true; | 310 static const bool hasIsEmptyValueFunction = true; |
| 311 static bool isEmptyValue(const Node& node) { return !node.m_next; } | 311 static bool isEmptyValue(const Node& node) { return !node.m_next; } |
| 312 | 312 |
| 313 static const int deletedValue = -1; | 313 static const int deletedValue = -1; |
| 314 | 314 |
| 315 static void constructDeletedValue(Node& slot, bool) { slot.m_next = reinterp
ret_cast<Node*>(deletedValue); } | 315 static void constructDeletedValue(Node& slot, bool) { slot.m_next = reinterpre
t_cast<Node*>(deletedValue); } |
| 316 static bool isDeletedValue(const Node& slot) { return slot.m_next == reinter
pret_cast<Node*>(deletedValue); } | 316 static bool isDeletedValue(const Node& slot) { return slot.m_next == reinterpr
et_cast<Node*>(deletedValue); } |
| 317 | 317 |
| 318 // Whether we need to trace and do weak processing depends on the traits of | 318 // Whether we need to trace and do weak processing depends on the traits of |
| 319 // the type inside the node. | 319 // the type inside the node. |
| 320 template<typename U = void> | 320 template <typename U = void> |
| 321 struct NeedsTracingLazily { | 321 struct NeedsTracingLazily { |
| 322 static const bool value = ValueTraits::template NeedsTracingLazily<>::va
lue; | 322 static const bool value = ValueTraits::template NeedsTracingLazily<>::value; |
| 323 }; | 323 }; |
| 324 static const WeakHandlingFlag weakHandlingFlag = ValueTraits::weakHandlingFl
ag; | 324 static const WeakHandlingFlag weakHandlingFlag = ValueTraits::weakHandlingFlag
; |
| 325 }; | 325 }; |
| 326 | 326 |
| 327 template<typename LinkedHashSetType> | 327 template <typename LinkedHashSetType> |
| 328 class LinkedHashSetIterator { | 328 class LinkedHashSetIterator { |
| 329 private: | 329 private: |
| 330 typedef typename LinkedHashSetType::Node Node; | 330 typedef typename LinkedHashSetType::Node Node; |
| 331 typedef typename LinkedHashSetType::Traits Traits; | 331 typedef typename LinkedHashSetType::Traits Traits; |
| 332 | 332 |
| 333 typedef typename LinkedHashSetType::Value& ReferenceType; | 333 typedef typename LinkedHashSetType::Value& ReferenceType; |
| 334 typedef typename LinkedHashSetType::Value* PointerType; | 334 typedef typename LinkedHashSetType::Value* PointerType; |
| 335 | 335 |
| 336 typedef LinkedHashSetConstIterator<LinkedHashSetType> const_iterator; | 336 typedef LinkedHashSetConstIterator<LinkedHashSetType> const_iterator; |
| 337 | 337 |
| 338 Node* node() { return const_cast<Node*>(m_iterator.node()); } | 338 Node* node() { return const_cast<Node*>(m_iterator.node()); } |
| 339 | 339 |
| 340 protected: | 340 protected: |
| 341 LinkedHashSetIterator(const Node* position, LinkedHashSetType* m_container) | 341 LinkedHashSetIterator(const Node* position, LinkedHashSetType* m_container) |
| 342 : m_iterator(position , m_container) | 342 : m_iterator(position, m_container) { |
| 343 { | 343 } |
| 344 } | 344 |
| 345 | 345 public: |
| 346 public: | 346 // Default copy, assignment and destructor are OK. |
| 347 // Default copy, assignment and destructor are OK. | 347 |
| 348 | 348 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } |
| 349 PointerType get() const { return const_cast<PointerType>(m_iterator.get());
} | 349 ReferenceType operator*() const { return *get(); } |
| 350 ReferenceType operator*() const { return *get(); } | 350 PointerType operator->() const { return get(); } |
| 351 PointerType operator->() const { return get(); } | 351 |
| 352 | 352 LinkedHashSetIterator& operator++() { |
| 353 LinkedHashSetIterator& operator++() { ++m_iterator; return *this; } | 353 ++m_iterator; |
| 354 LinkedHashSetIterator& operator--() { --m_iterator; return *this; } | 354 return *this; |
| 355 | 355 } |
| 356 // Postfix ++ and -- intentionally omitted. | 356 LinkedHashSetIterator& operator--() { |
| 357 | 357 --m_iterator; |
| 358 // Comparison. | 358 return *this; |
| 359 bool operator==(const LinkedHashSetIterator& other) const { return m_iterato
r == other.m_iterator; } | 359 } |
| 360 bool operator!=(const LinkedHashSetIterator& other) const { return m_iterato
r != other.m_iterator; } | 360 |
| 361 | 361 // Postfix ++ and -- intentionally omitted. |
| 362 operator const_iterator() const { return m_iterator; } | 362 |
| 363 | 363 // Comparison. |
| 364 protected: | 364 bool operator==(const LinkedHashSetIterator& other) const { return m_iterator
== other.m_iterator; } |
| 365 const_iterator m_iterator; | 365 bool operator!=(const LinkedHashSetIterator& other) const { return m_iterator
!= other.m_iterator; } |
| 366 template<typename T, typename U, typename V, typename W> friend class Linked
HashSet; | 366 |
| 367 }; | 367 operator const_iterator() const { return m_iterator; } |
| 368 | 368 |
| 369 template<typename LinkedHashSetType> | 369 protected: |
| 370 const_iterator m_iterator; |
| 371 template <typename T, typename U, typename V, typename W> |
| 372 friend class LinkedHashSet; |
| 373 }; |
| 374 |
| 375 template <typename LinkedHashSetType> |
| 370 class LinkedHashSetConstIterator { | 376 class LinkedHashSetConstIterator { |
| 371 private: | 377 private: |
| 372 typedef typename LinkedHashSetType::Node Node; | 378 typedef typename LinkedHashSetType::Node Node; |
| 373 typedef typename LinkedHashSetType::Traits Traits; | 379 typedef typename LinkedHashSetType::Traits Traits; |
| 374 | 380 |
| 375 typedef const typename LinkedHashSetType::Value& ReferenceType; | 381 typedef const typename LinkedHashSetType::Value& ReferenceType; |
| 376 typedef const typename LinkedHashSetType::Value* PointerType; | 382 typedef const typename LinkedHashSetType::Value* PointerType; |
| 377 | 383 |
| 378 const Node* node() const { return static_cast<const Node*>(m_position); } | 384 const Node* node() const { return static_cast<const Node*>(m_position); } |
| 379 | 385 |
| 380 protected: | 386 protected: |
| 381 LinkedHashSetConstIterator(const LinkedHashSetNodeBase* position, const Link
edHashSetType* container) | 387 LinkedHashSetConstIterator(const LinkedHashSetNodeBase* position, const Linked
HashSetType* container) |
| 382 : m_position(position) | 388 : m_position(position) |
| 383 #if ENABLE(ASSERT) | 389 #if ENABLE(ASSERT) |
| 384 , m_container(container) | 390 , |
| 385 , m_containerModifications(container->modifications()) | 391 m_container(container), |
| 392 m_containerModifications(container->modifications()) |
| 386 #endif | 393 #endif |
| 387 { | 394 { |
| 388 } | 395 } |
| 389 | 396 |
| 390 public: | 397 public: |
| 391 PointerType get() const | 398 PointerType get() const { |
| 392 { | 399 checkModifications(); |
| 393 checkModifications(); | 400 return &static_cast<const Node*>(m_position)->m_value; |
| 394 return &static_cast<const Node*>(m_position)->m_value; | 401 } |
| 395 } | 402 ReferenceType operator*() const { return *get(); } |
| 396 ReferenceType operator*() const { return *get(); } | 403 PointerType operator->() const { return get(); } |
| 397 PointerType operator->() const { return get(); } | 404 |
| 398 | 405 LinkedHashSetConstIterator& operator++() { |
| 399 LinkedHashSetConstIterator& operator++() | 406 ASSERT(m_position); |
| 400 { | 407 checkModifications(); |
| 401 ASSERT(m_position); | 408 m_position = m_position->m_next; |
| 402 checkModifications(); | 409 return *this; |
| 403 m_position = m_position->m_next; | 410 } |
| 404 return *this; | 411 |
| 405 } | 412 LinkedHashSetConstIterator& operator--() { |
| 406 | 413 ASSERT(m_position); |
| 407 LinkedHashSetConstIterator& operator--() | 414 checkModifications(); |
| 408 { | 415 m_position = m_position->m_prev; |
| 409 ASSERT(m_position); | 416 return *this; |
| 410 checkModifications(); | 417 } |
| 411 m_position = m_position->m_prev; | 418 |
| 412 return *this; | 419 // Postfix ++ and -- intentionally omitted. |
| 413 } | 420 |
| 414 | 421 // Comparison. |
| 415 // Postfix ++ and -- intentionally omitted. | 422 bool operator==(const LinkedHashSetConstIterator& other) const { |
| 416 | 423 return m_position == other.m_position; |
| 417 // Comparison. | 424 } |
| 418 bool operator==(const LinkedHashSetConstIterator& other) const | 425 bool operator!=(const LinkedHashSetConstIterator& other) const { |
| 419 { | 426 return m_position != other.m_position; |
| 420 return m_position == other.m_position; | 427 } |
| 421 } | 428 |
| 422 bool operator!=(const LinkedHashSetConstIterator& other) const | 429 private: |
| 423 { | 430 const LinkedHashSetNodeBase* m_position; |
| 424 return m_position != other.m_position; | |
| 425 } | |
| 426 | |
| 427 private: | |
| 428 const LinkedHashSetNodeBase* m_position; | |
| 429 #if ENABLE(ASSERT) | 431 #if ENABLE(ASSERT) |
| 430 void checkModifications() const { m_container->checkModifications(m_containe
rModifications); } | 432 void checkModifications() const { m_container->checkModifications(m_containerM
odifications); } |
| 431 const LinkedHashSetType* m_container; | 433 const LinkedHashSetType* m_container; |
| 432 int64_t m_containerModifications; | 434 int64_t m_containerModifications; |
| 433 #else | 435 #else |
| 434 void checkModifications() const { } | 436 void checkModifications() const {} |
| 435 #endif | 437 #endif |
| 436 template<typename T, typename U, typename V, typename W> friend class Linked
HashSet; | 438 template <typename T, typename U, typename V, typename W> |
| 437 friend class LinkedHashSetIterator<LinkedHashSetType>; | 439 friend class LinkedHashSet; |
| 438 }; | 440 friend class LinkedHashSetIterator<LinkedHashSetType>; |
| 439 | 441 }; |
| 440 template<typename LinkedHashSetType> | 442 |
| 443 template <typename LinkedHashSetType> |
| 441 class LinkedHashSetReverseIterator : public LinkedHashSetIterator<LinkedHashSetT
ype> { | 444 class LinkedHashSetReverseIterator : public LinkedHashSetIterator<LinkedHashSetT
ype> { |
| 442 typedef LinkedHashSetIterator<LinkedHashSetType> Superclass; | 445 typedef LinkedHashSetIterator<LinkedHashSetType> Superclass; |
| 443 typedef LinkedHashSetConstReverseIterator<LinkedHashSetType> const_reverse_i
terator; | 446 typedef LinkedHashSetConstReverseIterator<LinkedHashSetType> const_reverse_ite
rator; |
| 444 typedef typename LinkedHashSetType::Node Node; | 447 typedef typename LinkedHashSetType::Node Node; |
| 445 | 448 |
| 446 protected: | 449 protected: |
| 447 LinkedHashSetReverseIterator(const Node* position, LinkedHashSetType* contai
ner) | 450 LinkedHashSetReverseIterator(const Node* position, LinkedHashSetType* containe
r) |
| 448 : Superclass(position, container) { } | 451 : Superclass(position, container) {} |
| 449 | 452 |
| 450 public: | 453 public: |
| 451 LinkedHashSetReverseIterator& operator++() { Superclass::operator--(); retur
n *this; } | 454 LinkedHashSetReverseIterator& operator++() { |
| 452 LinkedHashSetReverseIterator& operator--() { Superclass::operator++(); retur
n *this; } | 455 Superclass::operator--(); |
| 453 | 456 return *this; |
| 454 // Postfix ++ and -- intentionally omitted. | 457 } |
| 455 | 458 LinkedHashSetReverseIterator& operator--() { |
| 456 operator const_reverse_iterator() const { return *reinterpret_cast<const_rev
erse_iterator*>(this); } | 459 Superclass::operator++(); |
| 457 | 460 return *this; |
| 458 template<typename T, typename U, typename V, typename W> friend class Linked
HashSet; | 461 } |
| 459 }; | 462 |
| 460 | 463 // Postfix ++ and -- intentionally omitted. |
| 461 template<typename LinkedHashSetType> | 464 |
| 465 operator const_reverse_iterator() const { return *reinterpret_cast<const_rever
se_iterator*>(this); } |
| 466 |
| 467 template <typename T, typename U, typename V, typename W> |
| 468 friend class LinkedHashSet; |
| 469 }; |
| 470 |
| 471 template <typename LinkedHashSetType> |
| 462 class LinkedHashSetConstReverseIterator : public LinkedHashSetConstIterator<Link
edHashSetType> { | 472 class LinkedHashSetConstReverseIterator : public LinkedHashSetConstIterator<Link
edHashSetType> { |
| 463 typedef LinkedHashSetConstIterator<LinkedHashSetType> Superclass; | 473 typedef LinkedHashSetConstIterator<LinkedHashSetType> Superclass; |
| 464 typedef typename LinkedHashSetType::Node Node; | 474 typedef typename LinkedHashSetType::Node Node; |
| 465 | 475 |
| 466 public: | 476 public: |
| 467 LinkedHashSetConstReverseIterator(const Node* position, const LinkedHashSetT
ype* container) | 477 LinkedHashSetConstReverseIterator(const Node* position, const LinkedHashSetTyp
e* container) |
| 468 : Superclass(position, container) { } | 478 : Superclass(position, container) {} |
| 469 | 479 |
| 470 LinkedHashSetConstReverseIterator& operator++() { Superclass::operator--();
return *this; } | 480 LinkedHashSetConstReverseIterator& operator++() { |
| 471 LinkedHashSetConstReverseIterator& operator--() { Superclass::operator++();
return *this; } | 481 Superclass::operator--(); |
| 472 | 482 return *this; |
| 473 // Postfix ++ and -- intentionally omitted. | 483 } |
| 474 | 484 LinkedHashSetConstReverseIterator& operator--() { |
| 475 template<typename T, typename U, typename V, typename W> friend class Linked
HashSet; | 485 Superclass::operator++(); |
| 476 }; | 486 return *this; |
| 477 | 487 } |
| 478 template<typename T, typename U, typename V, typename W> | 488 |
| 479 inline LinkedHashSet<T, U, V, W>::LinkedHashSet() { } | 489 // Postfix ++ and -- intentionally omitted. |
| 480 | 490 |
| 481 template<typename T, typename U, typename V, typename W> | 491 template <typename T, typename U, typename V, typename W> |
| 492 friend class LinkedHashSet; |
| 493 }; |
| 494 |
| 495 template <typename T, typename U, typename V, typename W> |
| 496 inline LinkedHashSet<T, U, V, W>::LinkedHashSet() {} |
| 497 |
| 498 template <typename T, typename U, typename V, typename W> |
| 482 inline LinkedHashSet<T, U, V, W>::LinkedHashSet(const LinkedHashSet& other) | 499 inline LinkedHashSet<T, U, V, W>::LinkedHashSet(const LinkedHashSet& other) |
| 483 : m_anchor() | 500 : m_anchor() { |
| 484 { | 501 const_iterator end = other.end(); |
| 485 const_iterator end = other.end(); | 502 for (const_iterator it = other.begin(); it != end; ++it) |
| 486 for (const_iterator it = other.begin(); it != end; ++it) | 503 add(*it); |
| 487 add(*it); | 504 } |
| 488 } | 505 |
| 489 | 506 template <typename T, typename U, typename V, typename W> |
| 490 template<typename T, typename U, typename V, typename W> | 507 inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=(const Lin
kedHashSet& other) { |
| 491 inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=(const Lin
kedHashSet& other) | 508 LinkedHashSet tmp(other); |
| 492 { | 509 swap(tmp); |
| 493 LinkedHashSet tmp(other); | 510 return *this; |
| 494 swap(tmp); | 511 } |
| 495 return *this; | 512 |
| 496 } | 513 template <typename T, typename U, typename V, typename W> |
| 497 | 514 inline void LinkedHashSet<T, U, V, W>::swap(LinkedHashSet& other) { |
| 498 template<typename T, typename U, typename V, typename W> | 515 m_impl.swap(other.m_impl); |
| 499 inline void LinkedHashSet<T, U, V, W>::swap(LinkedHashSet& other) | 516 swapAnchor(m_anchor, other.m_anchor); |
| 500 { | 517 } |
| 501 m_impl.swap(other.m_impl); | 518 |
| 502 swapAnchor(m_anchor, other.m_anchor); | 519 template <typename T, typename U, typename V, typename Allocator> |
| 503 } | 520 inline LinkedHashSet<T, U, V, Allocator>::~LinkedHashSet() { |
| 504 | 521 // The destructor of m_anchor will implicitly be called here, which will |
| 505 template<typename T, typename U, typename V, typename Allocator> | 522 // unlink the anchor from the collection. |
| 506 inline LinkedHashSet<T, U, V, Allocator>::~LinkedHashSet() | 523 } |
| 507 { | 524 |
| 508 // The destructor of m_anchor will implicitly be called here, which will | 525 template <typename T, typename U, typename V, typename W> |
| 509 // unlink the anchor from the collection. | 526 inline T& LinkedHashSet<T, U, V, W>::first() { |
| 510 } | 527 ASSERT(!isEmpty()); |
| 511 | 528 return firstNode()->m_value; |
| 512 template<typename T, typename U, typename V, typename W> | 529 } |
| 513 inline T& LinkedHashSet<T, U, V, W>::first() | 530 |
| 514 { | 531 template <typename T, typename U, typename V, typename W> |
| 515 ASSERT(!isEmpty()); | 532 inline const T& LinkedHashSet<T, U, V, W>::first() const { |
| 516 return firstNode()->m_value; | 533 ASSERT(!isEmpty()); |
| 517 } | 534 return firstNode()->m_value; |
| 518 | 535 } |
| 519 template<typename T, typename U, typename V, typename W> | 536 |
| 520 inline const T& LinkedHashSet<T, U, V, W>::first() const | 537 template <typename T, typename U, typename V, typename W> |
| 521 { | 538 inline void LinkedHashSet<T, U, V, W>::removeFirst() { |
| 522 ASSERT(!isEmpty()); | 539 ASSERT(!isEmpty()); |
| 523 return firstNode()->m_value; | 540 m_impl.remove(static_cast<Node*>(m_anchor.m_next)); |
| 524 } | 541 } |
| 525 | 542 |
| 526 template<typename T, typename U, typename V, typename W> | 543 template <typename T, typename U, typename V, typename W> |
| 527 inline void LinkedHashSet<T, U, V, W>::removeFirst() | 544 inline T& LinkedHashSet<T, U, V, W>::last() { |
| 528 { | 545 ASSERT(!isEmpty()); |
| 529 ASSERT(!isEmpty()); | 546 return lastNode()->m_value; |
| 530 m_impl.remove(static_cast<Node*>(m_anchor.m_next)); | 547 } |
| 531 } | 548 |
| 532 | 549 template <typename T, typename U, typename V, typename W> |
| 533 template<typename T, typename U, typename V, typename W> | 550 inline const T& LinkedHashSet<T, U, V, W>::last() const { |
| 534 inline T& LinkedHashSet<T, U, V, W>::last() | 551 ASSERT(!isEmpty()); |
| 535 { | 552 return lastNode()->m_value; |
| 536 ASSERT(!isEmpty()); | 553 } |
| 537 return lastNode()->m_value; | 554 |
| 538 } | 555 template <typename T, typename U, typename V, typename W> |
| 539 | 556 inline void LinkedHashSet<T, U, V, W>::removeLast() { |
| 540 template<typename T, typename U, typename V, typename W> | 557 ASSERT(!isEmpty()); |
| 541 inline const T& LinkedHashSet<T, U, V, W>::last() const | 558 m_impl.remove(static_cast<Node*>(m_anchor.m_prev)); |
| 542 { | 559 } |
| 543 ASSERT(!isEmpty()); | 560 |
| 544 return lastNode()->m_value; | 561 template <typename T, typename U, typename V, typename W> |
| 545 } | 562 inline typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::f
ind(ValuePeekInType value) { |
| 546 | 563 LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::NodeHashFunc
tions, ValuePeekInType>(value); |
| 547 template<typename T, typename U, typename V, typename W> | 564 if (!node) |
| 548 inline void LinkedHashSet<T, U, V, W>::removeLast() | 565 return end(); |
| 549 { | 566 return makeIterator(node); |
| 550 ASSERT(!isEmpty()); | 567 } |
| 551 m_impl.remove(static_cast<Node*>(m_anchor.m_prev)); | 568 |
| 552 } | 569 template <typename T, typename U, typename V, typename W> |
| 553 | 570 inline typename LinkedHashSet<T, U, V, W>::const_iterator LinkedHashSet<T, U, V,
W>::find(ValuePeekInType value) const { |
| 554 template<typename T, typename U, typename V, typename W> | 571 const LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::NodeHa
shFunctions, ValuePeekInType>(value); |
| 555 inline typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::f
ind(ValuePeekInType value) | 572 if (!node) |
| 556 { | 573 return end(); |
| 557 LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::NodeHashFu
nctions, ValuePeekInType>(value); | 574 return makeConstIterator(node); |
| 558 if (!node) | 575 } |
| 559 return end(); | 576 |
| 560 return makeIterator(node); | 577 template <typename Translator> |
| 561 } | |
| 562 | |
| 563 template<typename T, typename U, typename V, typename W> | |
| 564 inline typename LinkedHashSet<T, U, V, W>::const_iterator LinkedHashSet<T, U, V,
W>::find(ValuePeekInType value) const | |
| 565 { | |
| 566 const LinkedHashSet::Node* node = m_impl.template lookup<LinkedHashSet::Node
HashFunctions, ValuePeekInType>(value); | |
| 567 if (!node) | |
| 568 return end(); | |
| 569 return makeConstIterator(node); | |
| 570 } | |
| 571 | |
| 572 template<typename Translator> | |
| 573 struct LinkedHashSetTranslatorAdapter { | 578 struct LinkedHashSetTranslatorAdapter { |
| 574 template<typename T> static unsigned hash(const T& key) { return Translator:
:hash(key); } | 579 template <typename T> |
| 575 template<typename T, typename U> static bool equal(const T& a, const U& b) {
return Translator::equal(a.m_value, b); } | 580 static unsigned hash(const T& key) { return Translator::hash(key); } |
| 576 }; | 581 template <typename T, typename U> |
| 577 | 582 static bool equal(const T& a, const U& b) { return Translator::equal(a.m_value
, b); } |
| 578 template<typename Value, typename U, typename V, typename W> | 583 }; |
| 579 template<typename HashTranslator, typename T> | 584 |
| 580 inline typename LinkedHashSet<Value, U, V, W>::iterator LinkedHashSet<Value, U,
V, W>::find(const T& value) | 585 template <typename Value, typename U, typename V, typename W> |
| 581 { | 586 template <typename HashTranslator, typename T> |
| 582 typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions; | 587 inline typename LinkedHashSet<Value, U, V, W>::iterator LinkedHashSet<Value, U,
V, W>::find(const T& value) { |
| 583 const LinkedHashSet::Node* node = m_impl.template lookup<TranslatedFunctions
, const T&>(value); | 588 typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions; |
| 584 if (!node) | 589 const LinkedHashSet::Node* node = m_impl.template lookup<TranslatedFunctions,
const T&>(value); |
| 585 return end(); | 590 if (!node) |
| 586 return makeIterator(node); | 591 return end(); |
| 587 } | 592 return makeIterator(node); |
| 588 | 593 } |
| 589 template<typename Value, typename U, typename V, typename W> | 594 |
| 590 template<typename HashTranslator, typename T> | 595 template <typename Value, typename U, typename V, typename W> |
| 591 inline typename LinkedHashSet<Value, U, V, W>::const_iterator LinkedHashSet<Valu
e, U, V, W>::find(const T& value) const | 596 template <typename HashTranslator, typename T> |
| 592 { | 597 inline typename LinkedHashSet<Value, U, V, W>::const_iterator LinkedHashSet<Valu
e, U, V, W>::find(const T& value) const { |
| 593 typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions; | 598 typedef LinkedHashSetTranslatorAdapter<HashTranslator> TranslatedFunctions; |
| 594 const LinkedHashSet::Node* node = m_impl.template lookup<TranslatedFunctions
, const T&>(value); | 599 const LinkedHashSet::Node* node = m_impl.template lookup<TranslatedFunctions,
const T&>(value); |
| 595 if (!node) | 600 if (!node) |
| 596 return end(); | 601 return end(); |
| 597 return makeConstIterator(node); | 602 return makeConstIterator(node); |
| 598 } | 603 } |
| 599 | 604 |
| 600 template<typename Value, typename U, typename V, typename W> | 605 template <typename Value, typename U, typename V, typename W> |
| 601 template<typename HashTranslator, typename T> | 606 template <typename HashTranslator, typename T> |
| 602 inline bool LinkedHashSet<Value, U, V, W>::contains(const T& value) const | 607 inline bool LinkedHashSet<Value, U, V, W>::contains(const T& value) const { |
| 603 { | 608 return m_impl.template contains<LinkedHashSetTranslatorAdapter<HashTranslator>
>(value); |
| 604 return m_impl.template contains<LinkedHashSetTranslatorAdapter<HashTranslato
r>>(value); | 609 } |
| 605 } | 610 |
| 606 | 611 template <typename T, typename U, typename V, typename W> |
| 607 template<typename T, typename U, typename V, typename W> | 612 inline bool LinkedHashSet<T, U, V, W>::contains(ValuePeekInType value) const { |
| 608 inline bool LinkedHashSet<T, U, V, W>::contains(ValuePeekInType value) const | 613 return m_impl.template contains<NodeHashFunctions>(value); |
| 609 { | 614 } |
| 610 return m_impl.template contains<NodeHashFunctions>(value); | 615 |
| 611 } | 616 template <typename Value, typename HashFunctions, typename Traits, typename Allo
cator> |
| 612 | 617 typename LinkedHashSet<Value, HashFunctions, Traits, Allocator>::AddResult Linke
dHashSet<Value, HashFunctions, Traits, Allocator>::add(ValuePeekInType value) { |
| 613 template<typename Value, typename HashFunctions, typename Traits, typename Alloc
ator> | 618 return m_impl.template add<NodeHashFunctions>(value, &m_anchor); |
| 614 typename LinkedHashSet<Value, HashFunctions, Traits, Allocator>::AddResult Linke
dHashSet<Value, HashFunctions, Traits, Allocator>::add(ValuePeekInType value) | 619 } |
| 615 { | 620 |
| 616 return m_impl.template add<NodeHashFunctions>(value, &m_anchor); | 621 template <typename T, typename U, typename V, typename W> |
| 617 } | 622 typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::addRetur
nIterator(ValuePeekInType value) { |
| 618 | 623 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>(v
alue, &m_anchor); |
| 619 template<typename T, typename U, typename V, typename W> | 624 return makeIterator(result.storedValue); |
| 620 typename LinkedHashSet<T, U, V, W>::iterator LinkedHashSet<T, U, V, W>::addRetur
nIterator(ValuePeekInType value) | 625 } |
| 621 { | 626 |
| 622 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>
(value, &m_anchor); | 627 template <typename T, typename U, typename V, typename W> |
| 623 return makeIterator(result.storedValue); | 628 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::appendO
rMoveToLast(ValuePeekInType value) { |
| 624 } | 629 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>(v
alue, &m_anchor); |
| 625 | 630 Node* node = result.storedValue; |
| 626 template<typename T, typename U, typename V, typename W> | 631 if (!result.isNewEntry) { |
| 627 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::appendO
rMoveToLast(ValuePeekInType value) | 632 node->unlink(); |
| 628 { | 633 m_anchor.insertBefore(*node); |
| 629 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>
(value, &m_anchor); | 634 } |
| 630 Node* node = result.storedValue; | 635 return result; |
| 631 if (!result.isNewEntry) { | 636 } |
| 632 node->unlink(); | 637 |
| 633 m_anchor.insertBefore(*node); | 638 template <typename T, typename U, typename V, typename W> |
| 634 } | 639 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::prepend
OrMoveToFirst(ValuePeekInType value) { |
| 635 return result; | 640 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>(v
alue, m_anchor.m_next); |
| 636 } | 641 Node* node = result.storedValue; |
| 637 | 642 if (!result.isNewEntry) { |
| 638 template<typename T, typename U, typename V, typename W> | 643 node->unlink(); |
| 639 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::prepend
OrMoveToFirst(ValuePeekInType value) | 644 m_anchor.insertAfter(*node); |
| 640 { | 645 } |
| 641 typename ImplType::AddResult result = m_impl.template add<NodeHashFunctions>
(value, m_anchor.m_next); | 646 return result; |
| 642 Node* node = result.storedValue; | 647 } |
| 643 if (!result.isNewEntry) { | 648 |
| 644 node->unlink(); | 649 template <typename T, typename U, typename V, typename W> |
| 645 m_anchor.insertAfter(*node); | 650 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::insertB
efore(ValuePeekInType beforeValue, ValuePeekInType newValue) { |
| 646 } | 651 return insertBefore(find(beforeValue), newValue); |
| 647 return result; | 652 } |
| 648 } | 653 |
| 649 | 654 template <typename T, typename U, typename V, typename W> |
| 650 template<typename T, typename U, typename V, typename W> | 655 inline void LinkedHashSet<T, U, V, W>::remove(iterator it) { |
| 651 typename LinkedHashSet<T, U, V, W>::AddResult LinkedHashSet<T, U, V, W>::insertB
efore(ValuePeekInType beforeValue, ValuePeekInType newValue) | 656 if (it == end()) |
| 652 { | 657 return; |
| 653 return insertBefore(find(beforeValue), newValue); | 658 m_impl.remove(it.node()); |
| 654 } | 659 } |
| 655 | 660 |
| 656 template<typename T, typename U, typename V, typename W> | 661 template <typename T, typename U, typename V, typename W> |
| 657 inline void LinkedHashSet<T, U, V, W>::remove(iterator it) | 662 inline void LinkedHashSet<T, U, V, W>::remove(ValuePeekInType value) { |
| 658 { | 663 remove(find(value)); |
| 659 if (it == end()) | 664 } |
| 660 return; | 665 |
| 661 m_impl.remove(it.node()); | 666 inline void swapAnchor(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b) { |
| 662 } | 667 ASSERT(a.m_prev && a.m_next && b.m_prev && b.m_next); |
| 663 | 668 swap(a.m_prev, b.m_prev); |
| 664 template<typename T, typename U, typename V, typename W> | 669 swap(a.m_next, b.m_next); |
| 665 inline void LinkedHashSet<T, U, V, W>::remove(ValuePeekInType value) | 670 if (b.m_next == &a) { |
| 666 { | 671 ASSERT(b.m_prev == &a); |
| 667 remove(find(value)); | 672 b.m_next = &b; |
| 668 } | 673 b.m_prev = &b; |
| 669 | 674 } else { |
| 670 inline void swapAnchor(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b) | 675 b.m_next->m_prev = &b; |
| 671 { | 676 b.m_prev->m_next = &b; |
| 672 ASSERT(a.m_prev && a.m_next && b.m_prev && b.m_next); | 677 } |
| 673 swap(a.m_prev, b.m_prev); | 678 if (a.m_next == &b) { |
| 674 swap(a.m_next, b.m_next); | 679 ASSERT(a.m_prev == &b); |
| 675 if (b.m_next == &a) { | 680 a.m_next = &a; |
| 676 ASSERT(b.m_prev == &a); | 681 a.m_prev = &a; |
| 677 b.m_next = &b; | 682 } else { |
| 678 b.m_prev = &b; | 683 a.m_next->m_prev = &a; |
| 679 } else { | 684 a.m_prev->m_next = &a; |
| 680 b.m_next->m_prev = &b; | 685 } |
| 681 b.m_prev->m_next = &b; | 686 } |
| 682 } | 687 |
| 683 if (a.m_next == &b) { | 688 inline void swap(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b) { |
| 684 ASSERT(a.m_prev == &b); | 689 ASSERT(a.m_next != &a && b.m_next != &b); |
| 685 a.m_next = &a; | 690 swap(a.m_prev, b.m_prev); |
| 686 a.m_prev = &a; | 691 swap(a.m_next, b.m_next); |
| 687 } else { | 692 if (b.m_next) { |
| 688 a.m_next->m_prev = &a; | 693 b.m_next->m_prev = &b; |
| 689 a.m_prev->m_next = &a; | 694 b.m_prev->m_next = &b; |
| 690 } | 695 } |
| 691 } | 696 if (a.m_next) { |
| 692 | 697 a.m_next->m_prev = &a; |
| 693 inline void swap(LinkedHashSetNodeBase& a, LinkedHashSetNodeBase& b) | 698 a.m_prev->m_next = &a; |
| 694 { | 699 } |
| 695 ASSERT(a.m_next != &a && b.m_next != &b); | 700 } |
| 696 swap(a.m_prev, b.m_prev); | 701 |
| 697 swap(a.m_next, b.m_next); | 702 template <typename T, typename Allocator> |
| 698 if (b.m_next) { | 703 inline void swap(LinkedHashSetNode<T, Allocator>& a, LinkedHashSetNode<T, Alloca
tor>& b) { |
| 699 b.m_next->m_prev = &b; | 704 typedef LinkedHashSetNodeBase Base; |
| 700 b.m_prev->m_next = &b; | 705 // The key and value cannot be swapped atomically, and it would be |
| 701 } | 706 // wrong to have a GC when only one was swapped and the other still |
| 702 if (a.m_next) { | 707 // contained garbage (eg. from a previous use of the same slot). |
| 703 a.m_next->m_prev = &a; | 708 // Therefore we forbid a GC until both the key and the value are |
| 704 a.m_prev->m_next = &a; | 709 // swapped. |
| 705 } | 710 Allocator::enterGCForbiddenScope(); |
| 706 } | 711 swap(static_cast<Base&>(a), static_cast<Base&>(b)); |
| 707 | 712 swap(a.m_value, b.m_value); |
| 708 template<typename T, typename Allocator> | 713 Allocator::leaveGCForbiddenScope(); |
| 709 inline void swap(LinkedHashSetNode<T, Allocator>& a, LinkedHashSetNode<T, Alloca
tor>& b) | |
| 710 { | |
| 711 typedef LinkedHashSetNodeBase Base; | |
| 712 // The key and value cannot be swapped atomically, and it would be | |
| 713 // wrong to have a GC when only one was swapped and the other still | |
| 714 // contained garbage (eg. from a previous use of the same slot). | |
| 715 // Therefore we forbid a GC until both the key and the value are | |
| 716 // swapped. | |
| 717 Allocator::enterGCForbiddenScope(); | |
| 718 swap(static_cast<Base&>(a), static_cast<Base&>(b)); | |
| 719 swap(a.m_value, b.m_value); | |
| 720 Allocator::leaveGCForbiddenScope(); | |
| 721 } | 714 } |
| 722 | 715 |
| 723 #if !ENABLE(OILPAN) | 716 #if !ENABLE(OILPAN) |
| 724 template<typename T, typename U, typename V> | 717 template <typename T, typename U, typename V> |
| 725 struct NeedsTracing<LinkedHashSet<T, U, V>> { | 718 struct NeedsTracing<LinkedHashSet<T, U, V>> { |
| 726 static const bool value = false; | 719 static const bool value = false; |
| 727 }; | 720 }; |
| 728 #endif | 721 #endif |
| 729 | |
| 730 } | 722 } |
| 731 | 723 |
| 732 using WTF::LinkedHashSet; | 724 using WTF::LinkedHashSet; |
| 733 | 725 |
| 734 #endif /* WTF_LinkedHashSet_h */ | 726 #endif /* WTF_LinkedHashSet_h */ |
| OLD | NEW |