2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #ifndef WTF_ListHashSet_h
22 #define WTF_ListHashSet_h
24 #include "Assertions.h"
30 // ListHashSet: Just like HashSet, this class provides a Set
31 // interface - a collection of unique objects with O(1) insertion,
32 // removal and test for containership. However, it also has an
33 // order - iterating it will always give back values in the order
34 // in which they are added.
36 // In theory it would be possible to add prepend, insertAfter
37 // and an append that moves the element to the end even if already present,
38 // but unclear yet if these are needed.
40 template<typename Value
, typename HashFunctions
> class ListHashSet
;
42 template<typename T
> struct IdentityExtractor
;
44 template<typename Value
, typename HashFunctions
>
45 void deleteAllValues(const ListHashSet
<Value
, HashFunctions
>&);
47 template<typename ValueArg
, typename HashArg
> class ListHashSetIterator
;
48 template<typename ValueArg
, typename HashArg
> class ListHashSetConstIterator
;
50 template<typename ValueArg
> struct ListHashSetNode
;
51 template<typename ValueArg
> struct ListHashSetNodeAllocator
;
52 template<typename ValueArg
, typename HashArg
> struct ListHashSetNodeHashFunctions
;
54 template<typename ValueArg
, typename HashArg
= typename DefaultHash
<ValueArg
>::Hash
> class ListHashSet
{
56 typedef ListHashSetNode
<ValueArg
> Node
;
57 typedef ListHashSetNodeAllocator
<ValueArg
> NodeAllocator
;
59 typedef HashTraits
<Node
*> NodeTraits
;
60 typedef ListHashSetNodeHashFunctions
<ValueArg
, HashArg
> NodeHash
;
62 typedef HashTable
<Node
*, Node
*, IdentityExtractor
<Node
*>, NodeHash
, NodeTraits
, NodeTraits
> ImplType
;
63 typedef HashTableIterator
<Node
*, Node
*, IdentityExtractor
<Node
*>, NodeHash
, NodeTraits
, NodeTraits
> ImplTypeIterator
;
64 typedef HashTableConstIterator
<Node
*, Node
*, IdentityExtractor
<Node
*>, NodeHash
, NodeTraits
, NodeTraits
> ImplTypeConstIterator
;
66 typedef HashArg HashFunctions
;
69 typedef ValueArg ValueType
;
70 typedef ListHashSetIterator
<ValueType
, HashArg
> iterator
;
71 typedef ListHashSetConstIterator
<ValueType
, HashArg
> const_iterator
;
73 friend class ListHashSetConstIterator
<ValueType
, HashArg
>;
76 ListHashSet(const ListHashSet
&);
77 ListHashSet
& operator=(const ListHashSet
&);
80 void swap(ListHashSet
&);
88 const_iterator
begin() const;
89 const_iterator
end() const;
91 iterator
find(const ValueType
&);
92 const_iterator
find(const ValueType
&) const;
93 bool contains(const ValueType
&) const;
95 // the return value is a pair of an iterator to the new value's location,
96 // and a bool that is true if an new entry was added
97 pair
<iterator
, bool> add(const ValueType
&);
99 pair
<iterator
, bool> insertBefore(const ValueType
& beforeValue
, const ValueType
& newValue
);
100 pair
<iterator
, bool> insertBefore(iterator it
, const ValueType
&);
102 void remove(const ValueType
&);
103 void remove(iterator
);
107 void unlinkAndDelete(Node
*);
108 void appendNode(Node
*);
109 void insertNodeBefore(Node
* beforeNode
, Node
* newNode
);
110 void deleteAllNodes();
111 iterator
makeIterator(Node
*);
112 const_iterator
makeConstIterator(Node
*) const;
114 friend void deleteAllValues
<>(const ListHashSet
&);
119 OwnPtr
<NodeAllocator
> m_allocator
;
122 template<typename ValueArg
> struct ListHashSetNodeAllocator
{
123 typedef ListHashSetNode
<ValueArg
> Node
;
124 typedef ListHashSetNodeAllocator
<ValueArg
> NodeAllocator
;
126 ListHashSetNodeAllocator()
128 , m_isDoneWithInitialFreeList(false)
130 memset(m_pool
.pool
, 0, sizeof(m_pool
.pool
));
135 Node
* result
= m_freeList
;
138 return static_cast<Node
*>(fastMalloc(sizeof(Node
)));
140 ASSERT(!result
->m_isAllocated
);
142 Node
* next
= result
->m_next
;
143 ASSERT(!next
|| !next
->m_isAllocated
);
144 if (!next
&& !m_isDoneWithInitialFreeList
) {
146 if (next
== pastPool()) {
147 m_isDoneWithInitialFreeList
= true;
150 ASSERT(inPool(next
));
151 ASSERT(!next
->m_isAllocated
);
159 void deallocate(Node
* node
)
163 node
->m_isAllocated
= false;
165 node
->m_next
= m_freeList
;
174 Node
* pool() { return reinterpret_cast<Node
*>(m_pool
.pool
); }
175 Node
* pastPool() { return pool() + m_poolSize
; }
177 bool inPool(Node
* node
)
179 return node
>= pool() && node
< pastPool();
183 bool m_isDoneWithInitialFreeList
;
184 static const size_t m_poolSize
= 256;
186 char pool
[sizeof(Node
) * m_poolSize
];
191 template<typename ValueArg
> struct ListHashSetNode
{
192 typedef ListHashSetNodeAllocator
<ValueArg
> NodeAllocator
;
194 ListHashSetNode(ValueArg value
)
199 , m_isAllocated(true)
204 void* operator new(size_t, NodeAllocator
* allocator
)
206 return allocator
->allocate();
208 void destroy(NodeAllocator
* allocator
)
210 this->~ListHashSetNode();
211 allocator
->deallocate(this);
215 ListHashSetNode
* m_prev
;
216 ListHashSetNode
* m_next
;
223 template<typename ValueArg
, typename HashArg
> struct ListHashSetNodeHashFunctions
{
224 typedef ListHashSetNode
<ValueArg
> Node
;
226 static unsigned hash(Node
* const& key
) { return HashArg::hash(key
->m_value
); }
227 static bool equal(Node
* const& a
, Node
* const& b
) { return HashArg::equal(a
->m_value
, b
->m_value
); }
228 static const bool safeToCompareToEmptyOrDeleted
= false;
231 template<typename ValueArg
, typename HashArg
> class ListHashSetIterator
{
233 typedef ListHashSet
<ValueArg
, HashArg
> ListHashSetType
;
234 typedef ListHashSetIterator
<ValueArg
, HashArg
> iterator
;
235 typedef ListHashSetConstIterator
<ValueArg
, HashArg
> const_iterator
;
236 typedef ListHashSetNode
<ValueArg
> Node
;
237 typedef ValueArg ValueType
;
238 typedef ValueType
& ReferenceType
;
239 typedef ValueType
* PointerType
;
241 friend class ListHashSet
<ValueArg
, HashArg
>;
243 ListHashSetIterator(const ListHashSetType
* set
, Node
* position
) : m_iterator(set
, position
) { }
246 ListHashSetIterator() { }
248 // default copy, assignment and destructor are OK
250 PointerType
get() const { return const_cast<PointerType
>(m_iterator
.get()); }
251 ReferenceType
operator*() const { return *get(); }
252 PointerType
operator->() const { return get(); }
254 iterator
& operator++() { ++m_iterator
; return *this; }
256 // postfix ++ intentionally omitted
258 iterator
& operator--() { --m_iterator
; return *this; }
260 // postfix -- intentionally omitted
263 bool operator==(const iterator
& other
) const { return m_iterator
== other
.m_iterator
; }
264 bool operator!=(const iterator
& other
) const { return m_iterator
!= other
.m_iterator
; }
266 operator const_iterator() const { return m_iterator
; }
269 Node
* node() { return m_iterator
.node(); }
271 const_iterator m_iterator
;
274 template<typename ValueArg
, typename HashArg
> class ListHashSetConstIterator
{
276 typedef ListHashSet
<ValueArg
, HashArg
> ListHashSetType
;
277 typedef ListHashSetIterator
<ValueArg
, HashArg
> iterator
;
278 typedef ListHashSetConstIterator
<ValueArg
, HashArg
> const_iterator
;
279 typedef ListHashSetNode
<ValueArg
> Node
;
280 typedef ValueArg ValueType
;
281 typedef const ValueType
& ReferenceType
;
282 typedef const ValueType
* PointerType
;
284 friend class ListHashSet
<ValueArg
, HashArg
>;
285 friend class ListHashSetIterator
<ValueArg
, HashArg
>;
287 ListHashSetConstIterator(const ListHashSetType
* set
, Node
* position
)
289 , m_position(position
)
294 ListHashSetConstIterator()
298 PointerType
get() const
300 return &m_position
->m_value
;
302 ReferenceType
operator*() const { return *get(); }
303 PointerType
operator->() const { return get(); }
305 const_iterator
& operator++()
307 ASSERT(m_position
!= 0);
308 m_position
= m_position
->m_next
;
312 // postfix ++ intentionally omitted
314 const_iterator
& operator--()
316 ASSERT(m_position
!= m_set
->m_head
);
318 m_position
= m_set
->m_tail
;
320 m_position
= m_position
->m_prev
;
324 // postfix -- intentionally omitted
327 bool operator==(const const_iterator
& other
) const
329 return m_position
== other
.m_position
;
331 bool operator!=(const const_iterator
& other
) const
333 return m_position
!= other
.m_position
;
337 Node
* node() { return m_position
; }
339 const ListHashSetType
* m_set
;
344 template<typename ValueType
, typename HashFunctions
>
345 struct ListHashSetTranslator
{
347 typedef ListHashSetNode
<ValueType
> Node
;
348 typedef ListHashSetNodeAllocator
<ValueType
> NodeAllocator
;
350 static unsigned hash(const ValueType
& key
) { return HashFunctions::hash(key
); }
351 static bool equal(Node
* const& a
, const ValueType
& b
) { return HashFunctions::equal(a
->m_value
, b
); }
352 static void translate(Node
*& location
, const ValueType
& key
, NodeAllocator
* allocator
)
354 location
= new (allocator
) Node(key
);
358 template<typename T
, typename U
>
359 inline ListHashSet
<T
, U
>::ListHashSet()
362 , m_allocator(new NodeAllocator
)
366 template<typename T
, typename U
>
367 inline ListHashSet
<T
, U
>::ListHashSet(const ListHashSet
& other
)
370 , m_allocator(new NodeAllocator
)
372 const_iterator end
= other
.end();
373 for (const_iterator it
= other
.begin(); it
!= end
; ++it
)
377 template<typename T
, typename U
>
378 inline ListHashSet
<T
, U
>& ListHashSet
<T
, U
>::operator=(const ListHashSet
& other
)
380 ListHashSet
tmp(other
);
385 template<typename T
, typename U
>
386 inline void ListHashSet
<T
, U
>::swap(ListHashSet
& other
)
388 m_impl
.swap(other
.m_impl
);
389 std::swap(m_head
, other
.m_head
);
390 std::swap(m_tail
, other
.m_tail
);
391 m_allocator
.swap(other
.m_allocator
);
394 template<typename T
, typename U
>
395 inline ListHashSet
<T
, U
>::~ListHashSet()
400 template<typename T
, typename U
>
401 inline int ListHashSet
<T
, U
>::size() const
403 return m_impl
.size();
406 template<typename T
, typename U
>
407 inline int ListHashSet
<T
, U
>::capacity() const
409 return m_impl
.capacity();
412 template<typename T
, typename U
>
413 inline bool ListHashSet
<T
, U
>::isEmpty() const
415 return m_impl
.isEmpty();
418 template<typename T
, typename U
>
419 inline typename ListHashSet
<T
, U
>::iterator ListHashSet
<T
, U
>::begin()
421 return makeIterator(m_head
);
424 template<typename T
, typename U
>
425 inline typename ListHashSet
<T
, U
>::iterator ListHashSet
<T
, U
>::end()
427 return makeIterator(0);
430 template<typename T
, typename U
>
431 inline typename ListHashSet
<T
, U
>::const_iterator ListHashSet
<T
, U
>::begin() const
433 return makeConstIterator(m_head
);
436 template<typename T
, typename U
>
437 inline typename ListHashSet
<T
, U
>::const_iterator ListHashSet
<T
, U
>::end() const
439 return makeConstIterator(0);
442 template<typename T
, typename U
>
443 inline typename ListHashSet
<T
, U
>::iterator ListHashSet
<T
, U
>::find(const ValueType
& value
)
445 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
446 ImplTypeIterator it
= m_impl
.template find
<ValueType
, Translator
>(value
);
447 if (it
== m_impl
.end())
449 return makeIterator(*it
);
452 template<typename T
, typename U
>
453 inline typename ListHashSet
<T
, U
>::const_iterator ListHashSet
<T
, U
>::find(const ValueType
& value
) const
455 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
456 ImplTypeConstIterator it
= m_impl
.template find
<ValueType
, Translator
>(value
);
457 if (it
== m_impl
.end())
459 return makeConstIterator(*it
);
462 template<typename T
, typename U
>
463 inline bool ListHashSet
<T
, U
>::contains(const ValueType
& value
) const
465 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
466 return m_impl
.template contains
<ValueType
, Translator
>(value
);
469 template<typename T
, typename U
>
470 pair
<typename ListHashSet
<T
, U
>::iterator
, bool> ListHashSet
<T
, U
>::add(const ValueType
&value
)
472 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
473 pair
<typename
ImplType::iterator
, bool> result
= m_impl
.template add
<ValueType
, NodeAllocator
*, Translator
>(value
, m_allocator
.get());
475 appendNode(*result
.first
);
476 return std::make_pair(makeIterator(*result
.first
), result
.second
);
479 template<typename T
, typename U
>
480 pair
<typename ListHashSet
<T
, U
>::iterator
, bool> ListHashSet
<T
, U
>::insertBefore(iterator it
, const ValueType
& newValue
)
482 typedef ListHashSetTranslator
<ValueType
, HashFunctions
> Translator
;
483 pair
<typename
ImplType::iterator
, bool> result
= m_impl
.template add
<ValueType
, NodeAllocator
*, Translator
>(newValue
, m_allocator
.get());
485 insertNodeBefore(it
.node(), *result
.first
);
486 return std::make_pair(makeIterator(*result
.first
), result
.second
);
490 template<typename T
, typename U
>
491 pair
<typename ListHashSet
<T
, U
>::iterator
, bool> ListHashSet
<T
, U
>::insertBefore(const ValueType
& beforeValue
, const ValueType
& newValue
)
493 return insertBefore(find(beforeValue
), newValue
);
496 template<typename T
, typename U
>
497 inline void ListHashSet
<T
, U
>::remove(iterator it
)
501 m_impl
.remove(it
.node());
502 unlinkAndDelete(it
.node());
505 template<typename T
, typename U
>
506 inline void ListHashSet
<T
, U
>::remove(const ValueType
& value
)
511 template<typename T
, typename U
>
512 inline void ListHashSet
<T
, U
>::clear()
520 template<typename T
, typename U
>
521 void ListHashSet
<T
, U
>::unlinkAndDelete(Node
* node
)
524 ASSERT(node
== m_head
);
525 m_head
= node
->m_next
;
527 ASSERT(node
!= m_head
);
528 node
->m_prev
->m_next
= node
->m_next
;
532 ASSERT(node
== m_tail
);
533 m_tail
= node
->m_prev
;
535 ASSERT(node
!= m_tail
);
536 node
->m_next
->m_prev
= node
->m_prev
;
539 node
->destroy(m_allocator
.get());
542 template<typename T
, typename U
>
543 void ListHashSet
<T
, U
>::appendNode(Node
* node
)
545 node
->m_prev
= m_tail
;
550 m_tail
->m_next
= node
;
559 template<typename T
, typename U
>
560 void ListHashSet
<T
, U
>::insertNodeBefore(Node
* beforeNode
, Node
* newNode
)
563 return appendNode(newNode
);
565 newNode
->m_next
= beforeNode
;
566 newNode
->m_prev
= beforeNode
->m_prev
;
567 if (beforeNode
->m_prev
)
568 beforeNode
->m_prev
->m_next
= newNode
;
569 beforeNode
->m_prev
= newNode
;
571 if (!newNode
->m_prev
)
575 template<typename T
, typename U
>
576 void ListHashSet
<T
, U
>::deleteAllNodes()
581 for (Node
* node
= m_head
, *next
= m_head
->m_next
; node
; node
= next
, next
= node
? node
->m_next
: 0)
582 node
->destroy(m_allocator
.get());
585 template<typename T
, typename U
>
586 inline ListHashSetIterator
<T
, U
> ListHashSet
<T
, U
>::makeIterator(Node
* position
)
588 return ListHashSetIterator
<T
, U
>(this, position
);
591 template<typename T
, typename U
>
592 inline ListHashSetConstIterator
<T
, U
> ListHashSet
<T
, U
>::makeConstIterator(Node
* position
) const
594 return ListHashSetConstIterator
<T
, U
>(this, position
);
597 template<bool, typename ValueType
, typename HashTableType
>
598 void deleteAllValues(HashTableType
& collection
)
600 typedef typename
HashTableType::const_iterator iterator
;
601 iterator end
= collection
.end();
602 for (iterator it
= collection
.begin(); it
!= end
; ++it
)
603 delete (*it
)->m_value
;
606 template<typename T
, typename U
>
607 inline void deleteAllValues(const ListHashSet
<T
, U
>& collection
)
609 deleteAllValues
<true, typename ListHashSet
<T
, U
>::ValueType
>(collection
.m_impl
);
614 using WTF::ListHashSet
;
616 #endif /* WTF_ListHashSet_h */