1
// -*- mode: c++; c-basic-offset: 4 -*-
3
* Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
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.
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.
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.
22
#ifndef WTF_ListHashSet_h
23
#define WTF_ListHashSet_h
25
#include "Assertions.h"
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.
37
// In theory it would be possible to add prepend, insertAfter, insertBefore,
38
// and an append that moves the element to the end even if already present,
39
// but unclear yet if these are needed.
41
template<typename Value, typename HashFunctions> class ListHashSet;
43
template<typename T> struct IdentityExtractor;
45
template<typename Value, typename HashFunctions>
46
void deleteAllValues(const ListHashSet<Value, HashFunctions>&);
48
template<typename ValueArg, typename HashArg> class ListHashSetIterator;
49
template<typename ValueArg, typename HashArg> class ListHashSetConstIterator;
51
template<typename ValueArg> struct ListHashSetNode;
52
template<typename ValueArg> struct ListHashSetNodeAllocator;
53
template<typename ValueArg, typename HashArg> struct ListHashSetNodeHashFunctions;
55
template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet {
57
typedef ListHashSetNode<ValueArg> Node;
58
typedef ListHashSetNodeAllocator<ValueArg> NodeAllocator;
60
typedef HashTraits<Node*> NodeTraits;
61
typedef ListHashSetNodeHashFunctions<ValueArg, HashArg> NodeHash;
63
typedef HashTable<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplType;
65
typedef HashArg HashFunctions;
68
typedef ValueArg ValueType;
69
typedef ListHashSetIterator<ValueType, HashArg> iterator;
70
typedef ListHashSetConstIterator<ValueType, HashArg> const_iterator;
72
friend class ListHashSetConstIterator<ValueType, HashArg>;
75
ListHashSet(const ListHashSet&);
76
ListHashSet& operator=(const ListHashSet&);
79
void swap(ListHashSet&);
87
const_iterator begin() const;
88
const_iterator end() const;
90
iterator find(const ValueType&);
91
const_iterator find(const ValueType&) const;
92
bool contains(const ValueType&) const;
94
// the return value is a pair of an interator to the new value's location,
95
// and a bool that is true if an new entry was added
96
pair<iterator, bool> add(const ValueType&);
98
void remove(const ValueType&);
99
void remove(iterator);
103
void unlinkAndDelete(Node*);
104
void appendNode(Node*);
105
void deleteAllNodes();
106
iterator makeIterator(Node*);
107
const_iterator makeConstIterator(Node*) const;
109
friend void deleteAllValues<>(const ListHashSet&);
114
OwnPtr<NodeAllocator> m_allocator;
117
template<typename ValueArg> struct ListHashSetNodeAllocator {
118
typedef ListHashSetNode<ValueArg> Node;
119
typedef ListHashSetNodeAllocator<ValueArg> NodeAllocator;
121
ListHashSetNodeAllocator()
123
, m_isDoneWithInitialFreeList(false)
125
memset(m_pool.pool, 0, sizeof(m_pool.pool));
130
Node* result = m_freeList;
133
return static_cast<Node*>(fastMalloc(sizeof(Node)));
135
ASSERT(!result->m_isAllocated);
137
Node* next = result->m_next;
138
ASSERT(!next || !next->m_isAllocated);
139
if (!next && !m_isDoneWithInitialFreeList) {
141
if (next == pastPool()) {
142
m_isDoneWithInitialFreeList = true;
145
ASSERT(inPool(next));
146
ASSERT(!next->m_isAllocated);
154
void deallocate(Node* node)
158
node->m_isAllocated = false;
160
node->m_next = m_freeList;
169
Node* pool() { return reinterpret_cast<Node*>(m_pool.pool); }
170
Node* pastPool() { return pool() + m_poolSize; }
172
bool inPool(Node* node)
174
return node >= pool() && node < pastPool();
178
bool m_isDoneWithInitialFreeList;
179
static const size_t m_poolSize = 256;
181
char pool[sizeof(Node) * m_poolSize];
186
template<typename ValueArg> struct ListHashSetNode {
187
typedef ListHashSetNodeAllocator<ValueArg> NodeAllocator;
189
ListHashSetNode(ValueArg value)
194
, m_isAllocated(true)
199
void* operator new(size_t, NodeAllocator* allocator)
201
return allocator->allocate();
203
void destroy(NodeAllocator* allocator)
205
this->~ListHashSetNode();
206
allocator->deallocate(this);
210
ListHashSetNode* m_prev;
211
ListHashSetNode* m_next;
218
template<typename ValueArg, typename HashArg> struct ListHashSetNodeHashFunctions {
219
typedef ListHashSetNode<ValueArg> Node;
221
static unsigned hash(Node* const& key) { return HashArg::hash(key->m_value); }
222
static bool equal(Node* const& a, Node* const& b) { return HashArg::equal(a->m_value, b->m_value); }
225
template<typename ValueArg, typename HashArg> class ListHashSetIterator {
227
typedef ListHashSet<ValueArg, HashArg> ListHashSetType;
228
typedef ListHashSetIterator<ValueArg, HashArg> iterator;
229
typedef ListHashSetConstIterator<ValueArg, HashArg> const_iterator;
230
typedef ListHashSetNode<ValueArg> Node;
231
typedef ValueArg ValueType;
232
typedef ValueType& ReferenceType;
233
typedef ValueType* PointerType;
235
friend class ListHashSet<ValueArg, HashArg>;
237
ListHashSetIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { }
240
ListHashSetIterator() { }
242
// default copy, assignment and destructor are OK
244
PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
245
ReferenceType operator*() const { return *get(); }
246
PointerType operator->() const { return get(); }
248
iterator& operator++() { ++m_iterator; return *this; }
250
// postfix ++ intentionally omitted
252
iterator& operator--() { --m_iterator; return *this; }
254
// postfix -- intentionally omitted
257
bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
258
bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
260
operator const_iterator() const { return m_iterator; }
263
Node* node() { return m_iterator.node(); }
265
const_iterator m_iterator;
268
template<typename ValueArg, typename HashArg> class ListHashSetConstIterator {
270
typedef ListHashSet<ValueArg, HashArg> ListHashSetType;
271
typedef ListHashSetIterator<ValueArg, HashArg> iterator;
272
typedef ListHashSetConstIterator<ValueArg, HashArg> const_iterator;
273
typedef ListHashSetNode<ValueArg> Node;
274
typedef ValueArg ValueType;
275
typedef const ValueType& ReferenceType;
276
typedef const ValueType* PointerType;
278
friend class ListHashSet<ValueArg, HashArg>;
279
friend class ListHashSetIterator<ValueArg, HashArg>;
281
ListHashSetConstIterator(const ListHashSetType* set, Node* position)
283
, m_position(position)
288
ListHashSetConstIterator()
292
PointerType get() const
294
return &m_position->m_value;
296
ReferenceType operator*() const { return *get(); }
297
PointerType operator->() const { return get(); }
299
const_iterator& operator++()
301
ASSERT(m_position != 0);
302
m_position = m_position->m_next;
306
// postfix ++ intentionally omitted
308
const_iterator& operator--()
310
ASSERT(m_position != m_set->m_head);
311
m_position = m_position->m_prev;
315
// postfix -- intentionally omitted
318
bool operator==(const const_iterator& other) const
320
return m_position == other.m_position;
322
bool operator!=(const const_iterator& other) const
324
return m_position != other.m_position;
328
Node* node() { return m_position; }
330
const ListHashSetType* m_set;
335
template<typename ValueType, typename HashFunctions>
336
struct ListHashSetTranslator {
338
typedef ListHashSetNode<ValueType> Node;
339
typedef ListHashSetNodeAllocator<ValueType> NodeAllocator;
341
static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
342
static bool equal(Node* const& a, const ValueType& b) { return HashFunctions::equal(a->m_value, b); }
343
static void translate(Node*& location, const ValueType& key, NodeAllocator* allocator, unsigned)
345
location = new (allocator) Node(key);
349
template<typename T, typename U>
350
inline ListHashSet<T, U>::ListHashSet()
353
, m_allocator(new NodeAllocator)
357
template<typename T, typename U>
358
inline ListHashSet<T, U>::ListHashSet(const ListHashSet& other)
361
, m_allocator(new NodeAllocator)
363
const_iterator end = other.end();
364
for (const_iterator it = other.begin(); it != end; ++it)
368
template<typename T, typename U>
369
inline ListHashSet<T, U>& ListHashSet<T, U>::operator=(const ListHashSet& other)
371
ListHashSet tmp(other);
376
template<typename T, typename U>
377
inline void ListHashSet<T, U>::swap(ListHashSet& other)
379
m_impl.swap(other.m_impl);
380
std::swap(m_head, other.m_head);
381
std::swap(m_tail, other.m_tail);
382
m_allocator.swap(other.m_allocator);
386
template<typename T, typename U>
387
inline ListHashSet<T, U>::~ListHashSet()
392
template<typename T, typename U>
393
inline int ListHashSet<T, U>::size() const
395
return m_impl.size();
398
template<typename T, typename U>
399
inline int ListHashSet<T, U>::capacity() const
401
return m_impl.capacity();
404
template<typename T, typename U>
405
inline bool ListHashSet<T, U>::isEmpty() const
407
return m_impl.isEmpty();
410
template<typename T, typename U>
411
inline typename ListHashSet<T, U>::iterator ListHashSet<T, U>::begin()
413
return makeIterator(m_head);
416
template<typename T, typename U>
417
inline typename ListHashSet<T, U>::iterator ListHashSet<T, U>::end()
419
return makeIterator(0);
422
template<typename T, typename U>
423
inline typename ListHashSet<T, U>::const_iterator ListHashSet<T, U>::begin() const
425
return makeConstIterator(m_head);
428
template<typename T, typename U>
429
inline typename ListHashSet<T, U>::const_iterator ListHashSet<T, U>::end() const
431
return makeConstIterator(0);
434
template<typename T, typename U>
435
inline typename ListHashSet<T, U>::iterator ListHashSet<T, U>::find(const ValueType& value)
437
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
438
typename ImplType::iterator it = m_impl.template find<ValueType, Translator>(value);
439
if (it == m_impl.end())
441
return makeIterator(*it);
444
template<typename T, typename U>
445
inline typename ListHashSet<T, U>::const_iterator ListHashSet<T, U>::find(const ValueType& value) const
447
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
448
typename ImplType::const_iterator it = m_impl.template find<ValueType, Translator>(value);
449
if (it == m_impl.end())
451
return makeConstIterator(*it);
454
template<typename T, typename U>
455
inline bool ListHashSet<T, U>::contains(const ValueType& value) const
457
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
458
return m_impl.template contains<ValueType, Translator>(value);
461
template<typename T, typename U>
462
pair<typename ListHashSet<T, U>::iterator, bool> ListHashSet<T, U>::add(const ValueType &value)
464
typedef ListHashSetTranslator<ValueType, HashFunctions> Translator;
465
pair<typename ImplType::iterator, bool> result = m_impl.template add<ValueType, NodeAllocator*, Translator>(value, m_allocator.get());
467
appendNode(*result.first);
468
return std::make_pair(makeIterator(*result.first), result.second);
471
template<typename T, typename U>
472
inline void ListHashSet<T, U>::remove(iterator it)
476
m_impl.remove(it.node());
477
unlinkAndDelete(it.node());
480
template<typename T, typename U>
481
inline void ListHashSet<T, U>::remove(const ValueType& value)
486
template<typename T, typename U>
487
inline void ListHashSet<T, U>::clear()
495
template<typename T, typename U>
496
void ListHashSet<T, U>::unlinkAndDelete(Node* node)
499
ASSERT(node == m_head);
500
m_head = node->m_next;
502
ASSERT(node != m_head);
503
node->m_prev->m_next = node->m_next;
507
ASSERT(node == m_tail);
508
m_tail = node->m_prev;
510
ASSERT(node != m_tail);
511
node->m_next->m_prev = node->m_prev;
514
node->destroy(m_allocator.get());
517
template<typename T, typename U>
518
void ListHashSet<T, U>::appendNode(Node* node)
520
node->m_prev = m_tail;
525
m_tail->m_next = node;
534
template<typename T, typename U>
535
void ListHashSet<T, U>::deleteAllNodes()
540
for (Node* node = m_head, *next = m_head->m_next; node; node = next, next = node ? node->m_next : 0)
541
node->destroy(m_allocator.get());
544
template<typename T, typename U>
545
inline ListHashSetIterator<T, U> ListHashSet<T, U>::makeIterator(Node* position)
547
return ListHashSetIterator<T, U>(this, position);
550
template<typename T, typename U>
551
inline ListHashSetConstIterator<T, U> ListHashSet<T, U>::makeConstIterator(Node* position) const
553
return ListHashSetConstIterator<T, U>(this, position);
556
template<bool, typename ValueType, typename HashTableType>
557
void deleteAllValues(HashTableType& collection)
559
typedef typename HashTableType::const_iterator iterator;
560
iterator end = collection.end();
561
for (iterator it = collection.begin(); it != end; ++it)
562
delete (*it)->m_value;
565
template<typename T, typename U>
566
inline void deleteAllValues(const ListHashSet<T, U>& collection)
568
deleteAllValues<true, typename ListHashSet<T, U>::ValueType>(collection.m_impl);
573
using WTF::ListHashSet;
575
#endif /* WTF_ListHashSet_h */