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