]> git.ipfire.org Git - thirdparty/squid.git/blame - include/splay.h
MSVC fixup:
[thirdparty/squid.git] / include / splay.h
CommitLineData
0e2cd867 1/*
b001e822 2 * $Id: splay.h,v 1.27 2004/08/30 05:12:29 robertc Exp $
0e2cd867 3 */
4
b5638623 5#ifndef SQUID_SPLAY_H
6#define SQUID_SPLAY_H
3c01c392 7
b67e2c8c 8#ifndef __cplusplus
b67e2c8c 9#else
10
b8bad68c 11#include "Stack.h"
29b17d63 12
b67e2c8c 13template <class V>
42a503bd 14
15class SplayNode
16{
17
18public:
b67e2c8c 19 typedef V Value;
29b17d63 20 typedef int SPLAYCMP(Value const &a, Value const &b);
21 typedef void SPLAYFREE(Value &);
22 typedef void SPLAYWALKEE(Value const & nodedata, void *state);
00d77d6b 23 static void DefaultFree (Value &aValue) {delete aValue;}
42a503bd 24
2bcafc95 25 SplayNode<V> (Value const &);
29b17d63 26 Value data;
27 mutable SplayNode<V> *left;
28 mutable SplayNode<V> *right;
29 void destroy(SPLAYFREE *);
30 void walk(SPLAYWALKEE *, void *callerState);
4c50505b 31 SplayNode<V> const * start() const;
ccd33084 32 SplayNode<V> const * finish() const;
42a503bd 33
34 SplayNode<V> * remove
35 (const Value data, SPLAYCMP * compare);
36
29b17d63 37 SplayNode<V> * insert(Value data, SPLAYCMP * compare);
42a503bd 38
b001e822 39 template <class FindValue> SplayNode<V> * splay(const FindValue &data, int( * compare)(FindValue const &a, Value const &b)) const;
b67e2c8c 40};
41
29b17d63 42typedef SplayNode<void *> splayNode;
43
44template <class V>
42a503bd 45
b8bad68c 46class SplayConstIterator;
47
48template <class V>
49
ccd33084 50class SplayIterator;
51
52template <class V>
53
42a503bd 54class Splay
55{
56
57public:
29b17d63 58 typedef V Value;
59 typedef int SPLAYCMP(Value const &a, Value const &b);
42a503bd 60 typedef void SPLAYFREE(Value &);
b8bad68c 61 typedef SplayIterator<V> iterator;
62 typedef const SplayConstIterator<V> const_iterator;
0353e724 63 Splay():head(NULL), elements (0){}
42a503bd 64
29b17d63 65 mutable SplayNode<V> * head;
b001e822 66 template <class FindValue> Value const *find (FindValue const &, int( * compare)(FindValue const &a, Value const &b)) const;
0353e724 67 void insert(Value const &, SPLAYCMP *compare);
42a503bd 68
69 void remove
70 (Value const &, SPLAYCMP *compare);
71
72 void destroy(SPLAYFREE *);
73
4c50505b 74 SplayNode<V> const * start() const;
42a503bd 75
ccd33084 76 SplayNode<V> const * finish() const;
42a503bd 77
78 size_t size() const;
79
b8bad68c 80 const_iterator begin() const;
81
82 const_iterator end() const;
83
0353e724 84 size_t elements;
29b17d63 85};
b67e2c8c 86
b67e2c8c 87
88SQUIDCEXTERN int splayLastResult;
89
29b17d63 90SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, splayNode::SPLAYCMP *);
42a503bd 91
29b17d63 92SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, splayNode::SPLAYCMP *);
42a503bd 93
29b17d63 94SQUIDCEXTERN splayNode *splay_splay(const void **, splayNode *, splayNode::SPLAYCMP *);
42a503bd 95
29b17d63 96SQUIDCEXTERN void splay_destroy(splayNode *, splayNode::SPLAYFREE *);
42a503bd 97
29b17d63 98SQUIDCEXTERN void splay_walk(splayNode *, splayNode::SPLAYWALKEE *, void *callerState);
99
100/* inline methods */
101template<class V>
2bcafc95 102SplayNode<V>::SplayNode (Value const &someData) : data(someData), left(NULL), right (NULL) {}
103
87c692d7 104template<class V>
29b17d63 105void
106SplayNode<V>::walk(SPLAYWALKEE * walkee, void *state)
107{
108 if (this == NULL)
42a503bd 109 return;
110
29b17d63 111 if (left)
42a503bd 112 left->walk(walkee, state);
113
29b17d63 114 walkee(data, state);
42a503bd 115
29b17d63 116 if (right)
42a503bd 117 right->walk(walkee, state);
29b17d63 118}
119
4c50505b 120template<class V>
121SplayNode<V> const *
122SplayNode<V>::start() const
123{
124 if (this && left)
42a503bd 125 return left->start();
126
127 return this;
128}
129
130template<class V>
131SplayNode<V> const *
ccd33084 132SplayNode<V>::finish() const
42a503bd 133{
134 if (this && right)
ccd33084 135 return right->finish();
42a503bd 136
4c50505b 137 return this;
138}
139
29b17d63 140template<class V>
141void
142SplayNode<V>::destroy(SPLAYFREE * free_func)
143{
144 if (!this)
42a503bd 145 return;
146
29b17d63 147 if (left)
42a503bd 148 left->destroy(free_func);
149
29b17d63 150 if (right)
42a503bd 151 right->destroy(free_func);
152
29b17d63 153 free_func(data);
42a503bd 154
29b17d63 155 delete this;
156}
157
158template<class V>
159SplayNode<V> *
42a503bd 160SplayNode<V>::remove
161 (Value const dataToRemove, SPLAYCMP * compare)
29b17d63 162{
163 if (this == NULL)
42a503bd 164 return NULL;
165
626e1f97 166 SplayNode<V> *result = splay(dataToRemove, compare);
42a503bd 167
29b17d63 168 if (splayLastResult == 0) { /* found it */
42a503bd 169 SplayNode<V> *newTop;
170
171 if (result->left == NULL) {
172 newTop = result->right;
173 } else {
174 newTop = result->left->splay(dataToRemove, compare);
175 /* temporary */
176 newTop->right = result->right;
177 result->right = NULL;
178 }
179
180 delete result;
181 return newTop;
29b17d63 182 }
42a503bd 183
29b17d63 184 return result; /* It wasn't there */
185}
b67e2c8c 186
29b17d63 187template<class V>
188SplayNode<V> *
626e1f97 189SplayNode<V>::insert(Value dataToInsert, SPLAYCMP * compare)
29b17d63 190{
191 /* create node to insert */
2bcafc95 192 SplayNode<V> *newNode = new SplayNode<V>(dataToInsert);
42a503bd 193
29b17d63 194 if (this == NULL) {
42a503bd 195 splayLastResult = -1;
196 newNode->left = newNode->right = NULL;
197 return newNode;
29b17d63 198 }
42a503bd 199
626e1f97 200 SplayNode<V> *newTop = splay(dataToInsert, compare);
42a503bd 201
29b17d63 202 if (splayLastResult < 0) {
42a503bd 203 newNode->left = newTop->left;
204 newNode->right = newTop;
205 newTop->left = NULL;
206 return newNode;
29b17d63 207 } else if (splayLastResult > 0) {
42a503bd 208 newNode->right = newTop->right;
209 newNode->left = newTop;
210 newTop->right = NULL;
211 return newNode;
29b17d63 212 } else {
42a503bd 213 /* duplicate entry */
214 delete newNode;
215 return newTop;
29b17d63 216 }
217}
218
219template<class V>
b001e822 220template<class FindValue>
29b17d63 221SplayNode<V> *
b001e822 222SplayNode<V>::splay(FindValue const &dataToFind, int( * compare)(FindValue const &a, Value const &b)) const
29b17d63 223{
a46d2c0e 224 if (this == NULL) {
42a503bd 225 /* can't have compared successfully :} */
226 splayLastResult = -1;
227 return NULL;
a46d2c0e 228 }
42a503bd 229
b001e822 230 Value temp = Value();
231 SplayNode<V> N(temp);
29b17d63 232 SplayNode<V> *l;
233 SplayNode<V> *r;
234 SplayNode<V> *y;
235 N.left = N.right = NULL;
236 l = r = &N;
237
238 SplayNode<V> *top = const_cast<SplayNode<V> *>(this);
42a503bd 239
29b17d63 240 for (;;) {
42a503bd 241 splayLastResult = compare(dataToFind, top->data);
242
243 if (splayLastResult < 0) {
244 if (top->left == NULL)
245 break;
246
247 if ((splayLastResult = compare(dataToFind, top->left->data)) < 0) {
248 y = top->left; /* rotate right */
249 top->left = y->right;
250 y->right = top;
251 top = y;
252
253 if (top->left == NULL)
254 break;
255 }
256
257 r->left = top; /* link right */
258 r = top;
259 top = top->left;
260 } else if (splayLastResult > 0) {
261 if (top->right == NULL)
262 break;
263
264 if ((splayLastResult = compare(dataToFind, top->right->data)) > 0) {
265 y = top->right; /* rotate left */
266 top->right = y->left;
267 y->left = top;
268 top = y;
269
270 if (top->right == NULL)
271 break;
272 }
273
274 l->right = top; /* link left */
275 l = top;
276 top = top->right;
277 } else {
278 break;
279 }
29b17d63 280 }
42a503bd 281
29b17d63 282 l->right = top->left; /* assemble */
283 r->left = top->right;
284 top->left = N.right;
285 top->right = N.left;
286 return top;
287}
288
289template <class V>
b001e822 290template <class FindValue>
29b17d63 291typename Splay<V>::Value const *
b001e822 292Splay<V>::find (FindValue const &value, int( * compare)(FindValue const &a, Value const &b)) const
29b17d63 293{
294 head = head->splay(value, compare);
42a503bd 295
29b17d63 296 if (splayLastResult != 0)
42a503bd 297 return NULL;
298
29b17d63 299 return &head->data;
300}
b67e2c8c 301
0353e724 302template <class V>
303void
304Splay<V>::insert(Value const &value, SPLAYCMP *compare)
305{
306 assert (!find (value, compare));
307 head = head->insert(value, compare);
308 ++elements;
309}
310
311template <class V>
312void
42a503bd 313Splay<V>::remove
314 (Value const &value, SPLAYCMP *compare)
0353e724 315{
316 assert (find (value, compare));
42a503bd 317
318 head = head->remove
319 (value, compare);
320
0353e724 321 --elements;
322}
323
4c50505b 324template <class V>
42a503bd 325SplayNode<V> const *
326Splay<V>:: start() const
327{
328 if (head)
329 return head->start();
330
331 return NULL;
332}
333
334template <class V>
335SplayNode<V> const *
ccd33084 336Splay<V>:: finish() const
42a503bd 337{
4c50505b 338 if (head)
ccd33084 339 return head->finish();
42a503bd 340
4c50505b 341 return NULL;
342}
343
42a503bd 344template <class V>
345void
346Splay<V>:: destroy(SPLAYFREE *free_func)
347{
348 if (head)
349 head->destroy(free_func);
350
351 head = NULL;
352
353 elements = 0;
354}
355
356template <class V>
357size_t
358Splay<V>::size() const
359{
360 return elements;
361}
362
b8bad68c 363template <class V>
364typename Splay<V>::const_iterator
365Splay<V>::begin() const
366{
367 return const_iterator(head);
368}
369
370template <class V>
371typename Splay<V>::const_iterator
372Splay<V>::end() const
373{
374 return const_iterator(NULL);
375}
376
377template <class V>
378
379class SplayConstIterator
380{
381
382public:
383 typedef const V value_type;
384 SplayConstIterator (SplayNode<V> *aNode);
385 bool operator == (SplayConstIterator const &right) const;
386 SplayConstIterator operator ++ (int dummy);
387 SplayConstIterator &operator ++ ();
388 V const & operator * () const;
389
390private:
391 void advance();
392 void addLeftPath(SplayNode<V> *aNode);
393 void init(SplayNode<V> *);
394 Stack<SplayNode<V> *> toVisit;
395};
396
397template <class V>
398SplayConstIterator<V>::SplayConstIterator (SplayNode<V> *aNode)
399{
400 init(aNode);
401}
402
403template <class V>
404bool
405SplayConstIterator<V>::operator == (SplayConstIterator const &right) const
406{
407 return toVisit.top() == right.toVisit.top();
408}
409
410template <class V>
411SplayConstIterator<V> &
412SplayConstIterator<V>::operator ++ ()
413{
414 advance();
415 return *this;
416}
417
418template <class V>
419SplayConstIterator<V>
420SplayConstIterator<V>::operator ++ (int dummy)
421{
422 SplayConstIterator<V> result = *this;
423 advance();
424 return result;
425}
426
427/* advance is simple enough:
428* if the stack is empty, we're done.
429* otherwise, pop the last visited node
430* then, pop the next node to visit
431* if that has a right child, add it and it's
432* left-to-end path.
433* then add the node back.
434*/
435template <class V>
436void
437SplayConstIterator<V>::advance()
438{
439 if (toVisit.size() == 0)
440 return;
441
442 toVisit.pop();
443
444 if (toVisit.size() == 0)
445 return;
446
447 SplayNode<V> *currentNode = toVisit.pop();
448
449 addLeftPath(currentNode->right);
450
451 toVisit.push_back(currentNode);
452}
453
454template <class V>
455void
456SplayConstIterator<V>::addLeftPath(SplayNode<V> *aNode)
457{
458 if (aNode == NULL)
459 return;
460
461 do {
462 toVisit.push_back(aNode);
463 aNode = aNode->left;
464 } while (aNode != NULL);
465}
466
467template <class V>
468void
469SplayConstIterator<V>::init(SplayNode<V> *head)
470{
471 addLeftPath(head);
472}
473
474template <class V>
475V const &
476SplayConstIterator<V>::operator * () const
477{
478 /* can't dereference when past the end */
479
480 if (toVisit.size() == 0)
481 fatal ("Attempt to dereference SplayConstIterator past-the-end\n");
482
483 return toVisit.top()->data;
484}
485
486#endif /* cplusplus */
bdffbfa5 487
b5638623 488#endif /* SQUID_SPLAY_H */