1 /* 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved. 3 * Copyright (C) 2011, Benjamin Poulain <ikipou (at) gmail.com> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 * 20 */ 21 22 #ifndef WTF_ListHashSet_h 23 #define WTF_ListHashSet_h 24 25 #include "wtf/HashSet.h" 26 #include "wtf/OwnPtr.h" 27 #include "wtf/PassOwnPtr.h" 28 29 namespace WTF { 30 31 // ListHashSet: Just like HashSet, this class provides a Set 32 // interface - a collection of unique objects with O(1) insertion, 33 // removal and test for containership. However, it also has an 34 // order - iterating it will always give back values in the order 35 // in which they are added. 36 37 // Unlike iteration of most WTF Hash data structures, iteration is 38 // guaranteed safe against mutation of the ListHashSet, except for 39 // removal of the item currently pointed to by a given iterator. 40 41 template<typename Value, size_t inlineCapacity, typename HashFunctions> class ListHashSet; 42 43 template<typename Value, size_t inlineCapacity, typename HashFunctions> 44 void deleteAllValues(const ListHashSet<Value, inlineCapacity, HashFunctions>&); 45 46 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator; 47 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator; 48 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator; 49 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator; 50 51 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode; 52 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator; 53 54 template<typename HashArg> struct ListHashSetNodeHashFunctions; 55 template<typename HashArg> struct ListHashSetTranslator; 56 57 template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet { 58 WTF_MAKE_FAST_ALLOCATED; 59 private: 60 typedef ListHashSetNode<ValueArg, inlineCapacity> Node; 61 typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; 62 63 typedef HashTraits<Node*> NodeTraits; 64 typedef ListHashSetNodeHashFunctions<HashArg> NodeHash; 65 typedef ListHashSetTranslator<HashArg> BaseTranslator; 66 67 typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplType; 68 typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator; 69 typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator; 70 71 typedef HashArg HashFunctions; 72 73 public: 74 typedef ValueArg ValueType; 75 76 typedef ListHashSetIterator<ValueType, inlineCapacity, HashArg> iterator; 77 typedef ListHashSetConstIterator<ValueType, inlineCapacity, HashArg> const_iterator; 78 friend class ListHashSetConstIterator<ValueType, inlineCapacity, HashArg>; 79 80 typedef ListHashSetReverseIterator<ValueType, inlineCapacity, HashArg> reverse_iterator; 81 typedef ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg> const_reverse_iterator; 82 friend class ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg>; 83 84 typedef HashTableAddResult<iterator> AddResult; 85 86 ListHashSet(); 87 ListHashSet(const ListHashSet&); 88 ListHashSet& operator=(const ListHashSet&); 89 ~ListHashSet(); 90 91 void swap(ListHashSet&); 92 93 unsigned size() const; 94 unsigned capacity() const; 95 bool isEmpty() const; 96 97 size_t sizeInBytes() const; 98 99 iterator begin(); 100 iterator end(); 101 const_iterator begin() const; 102 const_iterator end() const; 103 104 reverse_iterator rbegin(); 105 reverse_iterator rend(); 106 const_reverse_iterator rbegin() const; 107 const_reverse_iterator rend() const; 108 109 ValueType& first(); 110 const ValueType& first() const; 111 void removeFirst(); 112 113 ValueType& last(); 114 const ValueType& last() const; 115 void removeLast(); 116 117 iterator find(const ValueType&); 118 const_iterator find(const ValueType&) const; 119 bool contains(const ValueType&) const; 120 121 // An alternate version of find() that finds the object by hashing and comparing 122 // with some other type, to avoid the cost of type conversion. 123 // The HashTranslator interface is defined in HashSet. 124 template<typename HashTranslator, typename T> iterator find(const T&); 125 template<typename HashTranslator, typename T> const_iterator find(const T&) const; 126 template<typename HashTranslator, typename T> bool contains(const T&) const; 127 128 // The return value of add is a pair of an iterator to the new value's location, 129 // and a bool that is true if an new entry was added. 130 AddResult add(const ValueType&); 131 132 // Add the value to the end of the collection. If the value was already in 133 // the list, it is moved to the end. 134 AddResult appendOrMoveToLast(const ValueType&); 135 136 // Add the value to the beginning of the collection. If the value was already in 137 // the list, it is moved to the beginning. 138 AddResult prependOrMoveToFirst(const ValueType&); 139 140 AddResult insertBefore(const ValueType& beforeValue, const ValueType& newValue); 141 AddResult insertBefore(iterator, const ValueType&); 142 143 void remove(const ValueType&); 144 void remove(iterator); 145 void clear(); 146 147 private: 148 void unlink(Node*); 149 void unlinkAndDelete(Node*); 150 void appendNode(Node*); 151 void prependNode(Node*); 152 void insertNodeBefore(Node* beforeNode, Node* newNode); 153 void deleteAllNodes(); 154 void createAllocatorIfNeeded(); 155 156 iterator makeIterator(Node*); 157 const_iterator makeConstIterator(Node*) const; 158 reverse_iterator makeReverseIterator(Node*); 159 const_reverse_iterator makeConstReverseIterator(Node*) const; 160 161 friend void deleteAllValues<>(const ListHashSet&); 162 163 ImplType m_impl; 164 Node* m_head; 165 Node* m_tail; 166 OwnPtr<NodeAllocator> m_allocator; 167 }; 168 169 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator { 170 typedef ListHashSetNode<ValueArg, inlineCapacity> Node; 171 typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; 172 173 ListHashSetNodeAllocator() 174 : m_freeList(pool()) 175 , m_isDoneWithInitialFreeList(false) 176 { 177 memset(m_pool.pool, 0, sizeof(m_pool.pool)); 178 } 179 180 Node* allocate() 181 { 182 Node* result = m_freeList; 183 184 if (!result) 185 return static_cast<Node*>(fastMalloc(sizeof(Node))); 186 187 ASSERT(!result->m_isAllocated); 188 189 Node* next = result->m_next; 190 ASSERT(!next || !next->m_isAllocated); 191 if (!next && !m_isDoneWithInitialFreeList) { 192 next = result + 1; 193 if (next == pastPool()) { 194 m_isDoneWithInitialFreeList = true; 195 next = 0; 196 } else { 197 ASSERT(inPool(next)); 198 ASSERT(!next->m_isAllocated); 199 } 200 } 201 m_freeList = next; 202 203 return result; 204 } 205 206 void deallocate(Node* node) 207 { 208 if (inPool(node)) { 209 #ifndef NDEBUG 210 node->m_isAllocated = false; 211 #endif 212 node->m_next = m_freeList; 213 m_freeList = node; 214 return; 215 } 216 217 fastFree(node); 218 } 219 220 bool inPool(Node* node) 221 { 222 return node >= pool() && node < pastPool(); 223 } 224 225 private: 226 Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); } 227 Node* pastPool() { return pool() + m_poolSize; } 228 229 Node* m_freeList; 230 bool m_isDoneWithInitialFreeList; 231 static const size_t m_poolSize = inlineCapacity; 232 union { 233 char pool[sizeof(Node) * m_poolSize]; 234 double forAlignment; 235 } m_pool; 236 }; 237 238 template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode { 239 typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; 240 241 ListHashSetNode(ValueArg value) 242 : m_value(value) 243 , m_prev(0) 244 , m_next(0) 245 #ifndef NDEBUG 246 , m_isAllocated(true) 247 #endif 248 { 249 } 250 251 void* operator new(size_t, NodeAllocator* allocator) 252 { 253 return allocator->allocate(); 254 } 255 void destroy(NodeAllocator* allocator) 256 { 257 this->~ListHashSetNode(); 258 allocator->deallocate(this); 259 } 260 261 ValueArg m_value; 262 ListHashSetNode* m_prev; 263 ListHashSetNode* m_next; 264 265 #ifndef NDEBUG 266 bool m_isAllocated; 267 #endif 268 }; 269 270 template<typename HashArg> struct ListHashSetNodeHashFunctions { 271 template<typename T> static unsigned hash(const T& key) { return HashArg::hash(key->m_value); } 272 template<typename T> static bool equal(const T& a, const T& b) { return HashArg::equal(a->m_value, b->m_value); } 273 static const bool safeToCompareToEmptyOrDeleted = false; 274 }; 275 276 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator { 277 private: 278 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; 279 typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator; 280 typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator; 281 typedef ListHashSetNode<ValueArg, inlineCapacity> Node; 282 typedef ValueArg ValueType; 283 typedef ValueType& ReferenceType; 284 typedef ValueType* PointerType; 285 286 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; 287 288 ListHashSetIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } 289 290 public: 291 ListHashSetIterator() { } 292 293 // default copy, assignment and destructor are OK 294 295 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } 296 ReferenceType operator*() const { return *get(); } 297 PointerType operator->() const { return get(); } 298 299 iterator& operator++() { ++m_iterator; return *this; } 300 301 // postfix ++ intentionally omitted 302 303 iterator& operator--() { --m_iterator; return *this; } 304 305 // postfix -- intentionally omitted 306 307 // Comparison. 308 bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } 309 bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } 310 311 operator const_iterator() const { return m_iterator; } 312 313 private: 314 Node* node() { return m_iterator.node(); } 315 316 const_iterator m_iterator; 317 }; 318 319 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator { 320 private: 321 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; 322 typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator; 323 typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator; 324 typedef ListHashSetNode<ValueArg, inlineCapacity> Node; 325 typedef ValueArg ValueType; 326 typedef const ValueType& ReferenceType; 327 typedef const ValueType* PointerType; 328 329 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; 330 friend class ListHashSetIterator<ValueArg, inlineCapacity, HashArg>; 331 332 ListHashSetConstIterator(const ListHashSetType* set, Node* position) 333 : m_set(set) 334 , m_position(position) 335 { 336 } 337 338 public: 339 ListHashSetConstIterator() 340 { 341 } 342 343 PointerType get() const 344 { 345 return &m_position->m_value; 346 } 347 ReferenceType operator*() const { return *get(); } 348 PointerType operator->() const { return get(); } 349 350 const_iterator& operator++() 351 { 352 ASSERT(m_position != 0); 353 m_position = m_position->m_next; 354 return *this; 355 } 356 357 // postfix ++ intentionally omitted 358 359 const_iterator& operator--() 360 { 361 ASSERT(m_position != m_set->m_head); 362 if (!m_position) 363 m_position = m_set->m_tail; 364 else 365 m_position = m_position->m_prev; 366 return *this; 367 } 368 369 // postfix -- intentionally omitted 370 371 // Comparison. 372 bool operator==(const const_iterator& other) const 373 { 374 return m_position == other.m_position; 375 } 376 bool operator!=(const const_iterator& other) const 377 { 378 return m_position != other.m_position; 379 } 380 381 private: 382 Node* node() { return m_position; } 383 384 const ListHashSetType* m_set; 385 Node* m_position; 386 }; 387 388 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator { 389 private: 390 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; 391 typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator; 392 typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator; 393 typedef ListHashSetNode<ValueArg, inlineCapacity> Node; 394 typedef ValueArg ValueType; 395 typedef ValueType& ReferenceType; 396 typedef ValueType* PointerType; 397 398 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; 399 400 ListHashSetReverseIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } 401 402 public: 403 ListHashSetReverseIterator() { } 404 405 // default copy, assignment and destructor are OK 406 407 PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } 408 ReferenceType operator*() const { return *get(); } 409 PointerType operator->() const { return get(); } 410 411 reverse_iterator& operator++() { ++m_iterator; return *this; } 412 413 // postfix ++ intentionally omitted 414 415 reverse_iterator& operator--() { --m_iterator; return *this; } 416 417 // postfix -- intentionally omitted 418 419 // Comparison. 420 bool operator==(const reverse_iterator& other) const { return m_iterator == other.m_iterator; } 421 bool operator!=(const reverse_iterator& other) const { return m_iterator != other.m_iterator; } 422 423 operator const_reverse_iterator() const { return m_iterator; } 424 425 private: 426 Node* node() { return m_iterator.node(); } 427 428 const_reverse_iterator m_iterator; 429 }; 430 431 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator { 432 private: 433 typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; 434 typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator; 435 typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator; 436 typedef ListHashSetNode<ValueArg, inlineCapacity> Node; 437 typedef ValueArg ValueType; 438 typedef const ValueType& ReferenceType; 439 typedef const ValueType* PointerType; 440 441 friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; 442 friend class ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg>; 443 444 ListHashSetConstReverseIterator(const ListHashSetType* set, Node* position) 445 : m_set(set) 446 , m_position(position) 447 { 448 } 449 450 public: 451 ListHashSetConstReverseIterator() 452 { 453 } 454 455 PointerType get() const 456 { 457 return &m_position->m_value; 458 } 459 ReferenceType operator*() const { return *get(); } 460 PointerType operator->() const { return get(); } 461 462 const_reverse_iterator& operator++() 463 { 464 ASSERT(m_position != 0); 465 m_position = m_position->m_prev; 466 return *this; 467 } 468 469 // postfix ++ intentionally omitted 470 471 const_reverse_iterator& operator--() 472 { 473 ASSERT(m_position != m_set->m_tail); 474 if (!m_position) 475 m_position = m_set->m_head; 476 else 477 m_position = m_position->m_next; 478 return *this; 479 } 480 481 // postfix -- intentionally omitted 482 483 // Comparison. 484 bool operator==(const const_reverse_iterator& other) const 485 { 486 return m_position == other.m_position; 487 } 488 bool operator!=(const const_reverse_iterator& other) const 489 { 490 return m_position != other.m_position; 491 } 492 493 private: 494 Node* node() { return m_position; } 495 496 const ListHashSetType* m_set; 497 Node* m_position; 498 }; 499 500 template<typename HashFunctions> 501 struct ListHashSetTranslator { 502 template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); } 503 template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); } 504 template<typename T, typename U, typename V> static void translate(T*& location, const U& key, const V& allocator) 505 { 506 location = new (allocator) T(key); 507 } 508 }; 509 510 template<typename T, size_t inlineCapacity, typename U> 511 inline ListHashSet<T, inlineCapacity, U>::ListHashSet() 512 : m_head(0) 513 , m_tail(0) 514 { 515 } 516 517 template<typename T, size_t inlineCapacity, typename U> 518 inline ListHashSet<T, inlineCapacity, U>::ListHashSet(const ListHashSet& other) 519 : m_head(0) 520 , m_tail(0) 521 { 522 const_iterator end = other.end(); 523 for (const_iterator it = other.begin(); it != end; ++it) 524 add(*it); 525 } 526 527 template<typename T, size_t inlineCapacity, typename U> 528 inline ListHashSet<T, inlineCapacity, U>& ListHashSet<T, inlineCapacity, U>::operator=(const ListHashSet& other) 529 { 530 ListHashSet tmp(other); 531 swap(tmp); 532 return *this; 533 } 534 535 template<typename T, size_t inlineCapacity, typename U> 536 inline void ListHashSet<T, inlineCapacity, U>::swap(ListHashSet& other) 537 { 538 m_impl.swap(other.m_impl); 539 std::swap(m_head, other.m_head); 540 std::swap(m_tail, other.m_tail); 541 m_allocator.swap(other.m_allocator); 542 } 543 544 template<typename T, size_t inlineCapacity, typename U> 545 inline ListHashSet<T, inlineCapacity, U>::~ListHashSet() 546 { 547 deleteAllNodes(); 548 } 549 550 template<typename T, size_t inlineCapacity, typename U> 551 inline unsigned ListHashSet<T, inlineCapacity, U>::size() const 552 { 553 return m_impl.size(); 554 } 555 556 template<typename T, size_t inlineCapacity, typename U> 557 inline unsigned ListHashSet<T, inlineCapacity, U>::capacity() const 558 { 559 return m_impl.capacity(); 560 } 561 562 template<typename T, size_t inlineCapacity, typename U> 563 inline bool ListHashSet<T, inlineCapacity, U>::isEmpty() const 564 { 565 return m_impl.isEmpty(); 566 } 567 568 template<typename T, size_t inlineCapacity, typename U> 569 size_t ListHashSet<T, inlineCapacity, U>::sizeInBytes() const 570 { 571 size_t result = sizeof(*this); 572 if (!m_allocator) 573 return result; 574 result += sizeof(*m_allocator) + (sizeof(typename ImplType::ValueType) * m_impl.capacity()); 575 for (Node* node = m_head; node; node = node->m_next) { 576 if (!m_allocator->inPool(node)) 577 result += sizeof(Node); 578 } 579 return result; 580 } 581 582 template<typename T, size_t inlineCapacity, typename U> 583 inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::begin() 584 { 585 return makeIterator(m_head); 586 } 587 588 template<typename T, size_t inlineCapacity, typename U> 589 inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::end() 590 { 591 return makeIterator(0); 592 } 593 594 template<typename T, size_t inlineCapacity, typename U> 595 inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::begin() const 596 { 597 return makeConstIterator(m_head); 598 } 599 600 template<typename T, size_t inlineCapacity, typename U> 601 inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::end() const 602 { 603 return makeConstIterator(0); 604 } 605 606 template<typename T, size_t inlineCapacity, typename U> 607 inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin() 608 { 609 return makeReverseIterator(m_tail); 610 } 611 612 template<typename T, size_t inlineCapacity, typename U> 613 inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rend() 614 { 615 return makeReverseIterator(0); 616 } 617 618 template<typename T, size_t inlineCapacity, typename U> 619 inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin() const 620 { 621 return makeConstReverseIterator(m_tail); 622 } 623 624 template<typename T, size_t inlineCapacity, typename U> 625 inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rend() const 626 { 627 return makeConstReverseIterator(0); 628 } 629 630 template<typename T, size_t inlineCapacity, typename U> 631 inline T& ListHashSet<T, inlineCapacity, U>::first() 632 { 633 ASSERT(!isEmpty()); 634 return m_head->m_value; 635 } 636 637 template<typename T, size_t inlineCapacity, typename U> 638 inline void ListHashSet<T, inlineCapacity, U>::removeFirst() 639 { 640 ASSERT(!isEmpty()); 641 m_impl.remove(m_head); 642 unlinkAndDelete(m_head); 643 } 644 645 template<typename T, size_t inlineCapacity, typename U> 646 inline const T& ListHashSet<T, inlineCapacity, U>::first() const 647 { 648 ASSERT(!isEmpty()); 649 return m_head->m_value; 650 } 651 652 template<typename T, size_t inlineCapacity, typename U> 653 inline T& ListHashSet<T, inlineCapacity, U>::last() 654 { 655 ASSERT(!isEmpty()); 656 return m_tail->m_value; 657 } 658 659 template<typename T, size_t inlineCapacity, typename U> 660 inline const T& ListHashSet<T, inlineCapacity, U>::last() const 661 { 662 ASSERT(!isEmpty()); 663 return m_tail->m_value; 664 } 665 666 template<typename T, size_t inlineCapacity, typename U> 667 inline void ListHashSet<T, inlineCapacity, U>::removeLast() 668 { 669 ASSERT(!isEmpty()); 670 m_impl.remove(m_tail); 671 unlinkAndDelete(m_tail); 672 } 673 674 template<typename T, size_t inlineCapacity, typename U> 675 inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) 676 { 677 ImplTypeIterator it = m_impl.template find<BaseTranslator>(value); 678 if (it == m_impl.end()) 679 return end(); 680 return makeIterator(*it); 681 } 682 683 template<typename T, size_t inlineCapacity, typename U> 684 inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) const 685 { 686 ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value); 687 if (it == m_impl.end()) 688 return end(); 689 return makeConstIterator(*it); 690 } 691 692 template<typename Translator> 693 struct ListHashSetTranslatorAdapter { 694 template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); } 695 template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); } 696 }; 697 698 template<typename ValueType, size_t inlineCapacity, typename U> 699 template<typename HashTranslator, typename T> 700 inline typename ListHashSet<ValueType, inlineCapacity, U>::iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) 701 { 702 ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); 703 if (it == m_impl.end()) 704 return end(); 705 return makeIterator(*it); 706 } 707 708 template<typename ValueType, size_t inlineCapacity, typename U> 709 template<typename HashTranslator, typename T> 710 inline typename ListHashSet<ValueType, inlineCapacity, U>::const_iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) const 711 { 712 ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); 713 if (it == m_impl.end()) 714 return end(); 715 return makeConstIterator(*it); 716 } 717 718 template<typename ValueType, size_t inlineCapacity, typename U> 719 template<typename HashTranslator, typename T> 720 inline bool ListHashSet<ValueType, inlineCapacity, U>::contains(const T& value) const 721 { 722 return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator> >(value); 723 } 724 725 template<typename T, size_t inlineCapacity, typename U> 726 inline bool ListHashSet<T, inlineCapacity, U>::contains(const ValueType& value) const 727 { 728 return m_impl.template contains<BaseTranslator>(value); 729 } 730 731 template<typename T, size_t inlineCapacity, typename U> 732 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::add(const ValueType &value) 733 { 734 createAllocatorIfNeeded(); 735 typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); 736 if (result.isNewEntry) 737 appendNode(*result.iterator); 738 return AddResult(makeIterator(*result.iterator), result.isNewEntry); 739 } 740 741 template<typename T, size_t inlineCapacity, typename U> 742 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::appendOrMoveToLast(const ValueType &value) 743 { 744 createAllocatorIfNeeded(); 745 typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); 746 Node* node = *result.iterator; 747 if (!result.isNewEntry) 748 unlink(node); 749 appendNode(node); 750 return AddResult(makeIterator(*result.iterator), result.isNewEntry); 751 } 752 753 template<typename T, size_t inlineCapacity, typename U> 754 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::prependOrMoveToFirst(const ValueType &value) 755 { 756 createAllocatorIfNeeded(); 757 typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); 758 Node* node = *result.iterator; 759 if (!result.isNewEntry) 760 unlink(node); 761 prependNode(node); 762 return AddResult(makeIterator(*result.iterator), result.isNewEntry); 763 } 764 765 template<typename T, size_t inlineCapacity, typename U> 766 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::insertBefore(iterator it, const ValueType& newValue) 767 { 768 createAllocatorIfNeeded(); 769 typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(newValue, m_allocator.get()); 770 if (result.isNewEntry) 771 insertNodeBefore(it.node(), *result.iterator); 772 return AddResult(makeIterator(*result.iterator), result.isNewEntry); 773 } 774 775 template<typename T, size_t inlineCapacity, typename U> 776 typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::insertBefore(const ValueType& beforeValue, const ValueType& newValue) 777 { 778 createAllocatorIfNeeded(); 779 return insertBefore(find(beforeValue), newValue); 780 } 781 782 template<typename T, size_t inlineCapacity, typename U> 783 inline void ListHashSet<T, inlineCapacity, U>::remove(iterator it) 784 { 785 if (it == end()) 786 return; 787 m_impl.remove(it.node()); 788 unlinkAndDelete(it.node()); 789 } 790 791 template<typename T, size_t inlineCapacity, typename U> 792 inline void ListHashSet<T, inlineCapacity, U>::remove(const ValueType& value) 793 { 794 remove(find(value)); 795 } 796 797 template<typename T, size_t inlineCapacity, typename U> 798 inline void ListHashSet<T, inlineCapacity, U>::clear() 799 { 800 deleteAllNodes(); 801 m_impl.clear(); 802 m_head = 0; 803 m_tail = 0; 804 } 805 806 template<typename T, size_t inlineCapacity, typename U> 807 void ListHashSet<T, inlineCapacity, U>::unlink(Node* node) 808 { 809 if (!node->m_prev) { 810 ASSERT(node == m_head); 811 m_head = node->m_next; 812 } else { 813 ASSERT(node != m_head); 814 node->m_prev->m_next = node->m_next; 815 } 816 817 if (!node->m_next) { 818 ASSERT(node == m_tail); 819 m_tail = node->m_prev; 820 } else { 821 ASSERT(node != m_tail); 822 node->m_next->m_prev = node->m_prev; 823 } 824 } 825 826 template<typename T, size_t inlineCapacity, typename U> 827 void ListHashSet<T, inlineCapacity, U>::unlinkAndDelete(Node* node) 828 { 829 unlink(node); 830 node->destroy(m_allocator.get()); 831 } 832 833 template<typename T, size_t inlineCapacity, typename U> 834 void ListHashSet<T, inlineCapacity, U>::appendNode(Node* node) 835 { 836 node->m_prev = m_tail; 837 node->m_next = 0; 838 839 if (m_tail) { 840 ASSERT(m_head); 841 m_tail->m_next = node; 842 } else { 843 ASSERT(!m_head); 844 m_head = node; 845 } 846 847 m_tail = node; 848 } 849 850 template<typename T, size_t inlineCapacity, typename U> 851 void ListHashSet<T, inlineCapacity, U>::prependNode(Node* node) 852 { 853 node->m_prev = 0; 854 node->m_next = m_head; 855 856 if (m_head) 857 m_head->m_prev = node; 858 else 859 m_tail = node; 860 861 m_head = node; 862 } 863 864 template<typename T, size_t inlineCapacity, typename U> 865 void ListHashSet<T, inlineCapacity, U>::insertNodeBefore(Node* beforeNode, Node* newNode) 866 { 867 if (!beforeNode) 868 return appendNode(newNode); 869 870 newNode->m_next = beforeNode; 871 newNode->m_prev = beforeNode->m_prev; 872 if (beforeNode->m_prev) 873 beforeNode->m_prev->m_next = newNode; 874 beforeNode->m_prev = newNode; 875 876 if (!newNode->m_prev) 877 m_head = newNode; 878 } 879 880 template<typename T, size_t inlineCapacity, typename U> 881 void ListHashSet<T, inlineCapacity, U>::deleteAllNodes() 882 { 883 if (!m_head) 884 return; 885 886 for (Node* node = m_head, *next = m_head->m_next; node; node = next, next = node ? node->m_next : 0) 887 node->destroy(m_allocator.get()); 888 } 889 890 template<typename T, size_t inlineCapacity, typename U> 891 void ListHashSet<T, inlineCapacity, U>::createAllocatorIfNeeded() 892 { 893 if (!m_allocator) 894 m_allocator = adoptPtr(new NodeAllocator); 895 } 896 897 template<typename T, size_t inlineCapacity, typename U> 898 inline ListHashSetReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeReverseIterator(Node* position) 899 { 900 return ListHashSetReverseIterator<T, inlineCapacity, U>(this, position); 901 } 902 903 template<typename T, size_t inlineCapacity, typename U> 904 inline ListHashSetConstReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstReverseIterator(Node* position) const 905 { 906 return ListHashSetConstReverseIterator<T, inlineCapacity, U>(this, position); 907 } 908 909 template<typename T, size_t inlineCapacity, typename U> 910 inline ListHashSetIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeIterator(Node* position) 911 { 912 return ListHashSetIterator<T, inlineCapacity, U>(this, position); 913 } 914 915 template<typename T, size_t inlineCapacity, typename U> 916 inline ListHashSetConstIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstIterator(Node* position) const 917 { 918 return ListHashSetConstIterator<T, inlineCapacity, U>(this, position); 919 } 920 template<bool, typename ValueType, typename HashTableType> 921 void deleteAllValues(HashTableType& collection) 922 { 923 typedef typename HashTableType::const_iterator iterator; 924 iterator end = collection.end(); 925 for (iterator it = collection.begin(); it != end; ++it) 926 delete (*it)->m_value; 927 } 928 929 template<typename T, size_t inlineCapacity, typename U> 930 inline void deleteAllValues(const ListHashSet<T, inlineCapacity, U>& collection) 931 { 932 deleteAllValues<true, typename ListHashSet<T, inlineCapacity, U>::ValueType>(collection.m_impl); 933 } 934 935 } // namespace WTF 936 937 using WTF::ListHashSet; 938 939 #endif /* WTF_ListHashSet_h */ 940