]> git.ipfire.org Git - thirdparty/squid.git/blame - include/splay.h
Bootstrapped
[thirdparty/squid.git] / include / splay.h
CommitLineData
0e2cd867 1/*
4c50505b 2 * $Id: splay.h,v 1.20 2003/06/24 12:30:59 robertc Exp $
0e2cd867 3 */
4
b5638623 5#ifndef SQUID_SPLAY_H
6#define SQUID_SPLAY_H
3c01c392 7
b67e2c8c 8#ifndef __cplusplus
9/* legacy C bindings - can be removed when mempool is C++ */
3c01c392 10typedef struct _splay_node {
5b220cbf 11 void *data;
12 struct _splay_node *left;
13 struct _splay_node *right;
3c01c392 14} splayNode;
15
29b17d63 16typedef int SPLAYCMP(const void **a, const void **b);
17typedef void SPLAYWALKEE(void **nodedata, void *state);
3c01c392 18
e6ccf245 19SQUIDCEXTERN int splayLastResult;
3c01c392 20
29b17d63 21/* MUST match C++ prototypes */
e6ccf245 22SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, SPLAYCMP *);
29b17d63 23SQUIDCEXTERN splayNode *splay_splay(const void **, splayNode *, SPLAYCMP *);
e6ccf245 24SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, SPLAYCMP *);
e6ccf245 25SQUIDCEXTERN void splay_walk(splayNode *, SPLAYWALKEE *, void *);
b67e2c8c 26#else
27
29b17d63 28
b67e2c8c 29template <class V>
30class SplayNode {
31 public:
32 typedef V Value;
29b17d63 33 typedef int SPLAYCMP(Value const &a, Value const &b);
34 typedef void SPLAYFREE(Value &);
35 typedef void SPLAYWALKEE(Value const & nodedata, void *state);
8000a965 36 static void DefaultFree (Value &aValue) {aValue->deleteSelf();}
29b17d63 37 Value data;
38 mutable SplayNode<V> *left;
39 mutable SplayNode<V> *right;
40 void destroy(SPLAYFREE *);
41 void walk(SPLAYWALKEE *, void *callerState);
4c50505b 42 SplayNode<V> const * start() const;
29b17d63 43 SplayNode<V> * remove(const Value data, SPLAYCMP * compare);
44 SplayNode<V> * insert(Value data, SPLAYCMP * compare);
45 SplayNode<V> * splay(const Value &data, SPLAYCMP * compare) const;
b67e2c8c 46};
47
29b17d63 48typedef SplayNode<void *> splayNode;
49
50template <class V>
51class Splay {
52 public:
53 typedef V Value;
54 typedef int SPLAYCMP(Value const &a, Value const &b);
0353e724 55 Splay():head(NULL), elements (0){}
29b17d63 56 mutable SplayNode<V> * head;
57 Value const *find (Value const &, SPLAYCMP *compare) const;
0353e724 58 void insert(Value const &, SPLAYCMP *compare);
59 void remove(Value const &, SPLAYCMP *compare);
4c50505b 60 SplayNode<V> const * start() const;
0353e724 61 size_t elements;
29b17d63 62};
b67e2c8c 63
b67e2c8c 64
65SQUIDCEXTERN int splayLastResult;
66
29b17d63 67SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, splayNode::SPLAYCMP *);
68SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, splayNode::SPLAYCMP *);
69SQUIDCEXTERN splayNode *splay_splay(const void **, splayNode *, splayNode::SPLAYCMP *);
70SQUIDCEXTERN void splay_destroy(splayNode *, splayNode::SPLAYFREE *);
71SQUIDCEXTERN void splay_walk(splayNode *, splayNode::SPLAYWALKEE *, void *callerState);
72
73/* inline methods */
74template<class V>
75void
76SplayNode<V>::walk(SPLAYWALKEE * walkee, void *state)
77{
78 if (this == NULL)
79 return;
80 if (left)
81 left->walk(walkee, state);
82 walkee(data, state);
83 if (right)
84 right->walk(walkee, state);
85}
86
4c50505b 87template<class V>
88SplayNode<V> const *
89SplayNode<V>::start() const
90{
91 if (this && left)
92 return left->start();
93 return this;
94}
95
29b17d63 96template<class V>
97void
98SplayNode<V>::destroy(SPLAYFREE * free_func)
99{
100 if (!this)
101 return;
102 if (left)
103 left->destroy(free_func);
104 if (right)
105 right->destroy(free_func);
106 free_func(data);
107 delete this;
108}
109
110template<class V>
111SplayNode<V> *
626e1f97 112SplayNode<V>::remove(Value const dataToRemove, SPLAYCMP * compare)
29b17d63 113{
114 if (this == NULL)
115 return NULL;
626e1f97 116 SplayNode<V> *result = splay(dataToRemove, compare);
29b17d63 117 if (splayLastResult == 0) { /* found it */
118 SplayNode<V> *newTop;
119 if (result->left == NULL) {
120 newTop = result->right;
121 } else {
626e1f97 122 newTop = result->left->splay(dataToRemove, compare);
29b17d63 123 /* temporary */
124 newTop->right = result->right;
125 result->right = NULL;
126 }
127 delete result;
128 return newTop;
129 }
130 return result; /* It wasn't there */
131}
b67e2c8c 132
29b17d63 133template<class V>
134SplayNode<V> *
626e1f97 135SplayNode<V>::insert(Value dataToInsert, SPLAYCMP * compare)
29b17d63 136{
137 /* create node to insert */
138 SplayNode<V> *newNode = new SplayNode<V>;
626e1f97 139 newNode->data = dataToInsert;
29b17d63 140 if (this == NULL) {
0353e724 141 splayLastResult = -1;
29b17d63 142 newNode->left = newNode->right = NULL;
143 return newNode;
144 }
145
626e1f97 146 SplayNode<V> *newTop = splay(dataToInsert, compare);
29b17d63 147 if (splayLastResult < 0) {
148 newNode->left = newTop->left;
149 newNode->right = newTop;
150 newTop->left = NULL;
151 return newNode;
152 } else if (splayLastResult > 0) {
153 newNode->right = newTop->right;
154 newNode->left = newTop;
155 newTop->right = NULL;
156 return newNode;
157 } else {
158 /* duplicate entry */
159 delete newNode;
160 return newTop;
161 }
162}
163
164template<class V>
165SplayNode<V> *
626e1f97 166SplayNode<V>::splay(Value const &dataToFind, SPLAYCMP * compare) const
29b17d63 167{
a46d2c0e 168 if (this == NULL) {
169 /* can't have compared successfully :} */
170 splayLastResult = -1;
29b17d63 171 return NULL;
a46d2c0e 172 }
29b17d63 173 SplayNode<V> N;
174 SplayNode<V> *l;
175 SplayNode<V> *r;
176 SplayNode<V> *y;
177 N.left = N.right = NULL;
178 l = r = &N;
179
180 SplayNode<V> *top = const_cast<SplayNode<V> *>(this);
181 for (;;) {
626e1f97 182 splayLastResult = compare(dataToFind, top->data);
29b17d63 183 if (splayLastResult < 0) {
184 if (top->left == NULL)
185 break;
626e1f97 186 if ((splayLastResult = compare(dataToFind, top->left->data)) < 0) {
29b17d63 187 y = top->left; /* rotate right */
188 top->left = y->right;
189 y->right = top;
190 top = y;
191 if (top->left == NULL)
192 break;
193 }
194 r->left = top; /* link right */
195 r = top;
196 top = top->left;
197 } else if (splayLastResult > 0) {
198 if (top->right == NULL)
199 break;
626e1f97 200 if ((splayLastResult = compare(dataToFind, top->right->data)) > 0) {
29b17d63 201 y = top->right; /* rotate left */
202 top->right = y->left;
203 y->left = top;
204 top = y;
205 if (top->right == NULL)
206 break;
207 }
208 l->right = top; /* link left */
209 l = top;
210 top = top->right;
211 } else {
212 break;
213 }
214 }
215 l->right = top->left; /* assemble */
216 r->left = top->right;
217 top->left = N.right;
218 top->right = N.left;
219 return top;
220}
221
222template <class V>
223typename Splay<V>::Value const *
224Splay<V>::find (Value const &value, SPLAYCMP *compare) const
225{
226 head = head->splay(value, compare);
227 if (splayLastResult != 0)
228 return NULL;
229 return &head->data;
230}
b67e2c8c 231
0353e724 232template <class V>
233void
234Splay<V>::insert(Value const &value, SPLAYCMP *compare)
235{
236 assert (!find (value, compare));
237 head = head->insert(value, compare);
238 ++elements;
239}
240
241template <class V>
242void
243Splay<V>::remove(Value const &value, SPLAYCMP *compare)
244{
245 assert (find (value, compare));
246 head = head->remove(value, compare);
247 --elements;
248}
249
4c50505b 250template <class V>
251SplayNode<V> const *
252Splay<V>:: start() const{
253 if (head)
254 return head->start();
255 return NULL;
256}
257
b67e2c8c 258#endif
bdffbfa5 259
b5638623 260#endif /* SQUID_SPLAY_H */