1 /*
2 Copyright (c) 2011, Willem-Hendrik Thiart
3 Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * The names of its contributors may not be used to endorse or promote
14 products derived from this software without specific prior written
15 permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL WILLEM-HENDRIK THIART BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "iwstree.h"
30 #include "iwlog.h"
31 #include <stdlib.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <errno.h>
35 #include <stdint.h>
36
37 typedef struct tree_node_s {
38 struct tree_node_s *left;
39 struct tree_node_s *right;
40 void *key;
41 void *value;
42 } tree_node_t;
43
44
45 struct tree_iter_s {
46 IWSTREE *st; /**< Owner tree */
47 int spos; /**< Position of top element stack */
48 int slen; /**< Max number of elements in stack */
49 tree_node_t **stack; /**< Bottom of iterator stack */
50 };
51
iwstree_str_cmp(const void * o1,const void * o2)52 int iwstree_str_cmp(const void *o1, const void *o2) {
53 return strcmp(o1, o2);
54 }
55
iwstree_uint64_cmp(const void * o1,const void * o2)56 int iwstree_uint64_cmp(const void *o1, const void *o2) {
57 uint64_t v1 = *(uint64_t *) o1;
58 uint64_t v2 = *(uint64_t *) o2;
59 return v1 > v2 ? 1 : v1 < v2 ? -1 : 0;
60 }
61
iwstree_int64_cmp(const void * o1,const void * o2)62 int iwstree_int64_cmp(const void *o1, const void *o2) {
63 int64_t v1 = *(int64_t *) o1;
64 int64_t v2 = *(int64_t *) o2;
65 return v1 > v2 ? 1 : v1 < v2 ? -1 : 0;
66 }
67
_cmp_default(const void * k1,const void * k2)68 static int _cmp_default(const void *k1, const void *k2) {
69 return k1 < k2 ? -1 : k1 > k2 ? 1 : 0;
70 }
71
iwstree_create(int (* cmp)(const void *,const void *),void (* kvfree)(void *,void *))72 IWSTREE *iwstree_create(int (*cmp)(const void *, const void *),
73 void (*kvfree)(void *, void *)) {
74 IWSTREE *st;
75 st = malloc(sizeof(IWSTREE));
76 if (!st) {
77 return 0;
78 }
79 memset(st, 0, sizeof(IWSTREE));
80 if (!cmp) {
81 cmp = _cmp_default;
82 }
83 st->cmp = cmp;
84 st->kvfree = kvfree;
85 return st;
86 }
87
_free_node(IWSTREE * st,tree_node_t * node)88 static void _free_node(IWSTREE *st, tree_node_t *node) {
89 if (node) {
90 _free_node(st, node->left);
91 _free_node(st, node->right);
92 if (st->kvfree) {
93 st->kvfree(node->key, node->value);
94 }
95 free(node);
96 }
97 }
98
iwstree_clear(IWSTREE * st)99 void iwstree_clear(IWSTREE *st) {
100 if (st) {
101 _free_node(st, st->root);
102 st->root = 0;
103 }
104 }
105
iwstree_destroy(IWSTREE * st)106 void iwstree_destroy(IWSTREE *st) {
107 iwstree_clear(st);
108 free(st);
109 }
110
_init_node(void * key,void * value)111 static tree_node_t *_init_node(void *key, void *value) {
112 tree_node_t *n;
113 n = malloc(sizeof(tree_node_t));
114 if (!n) {
115 return 0;
116 }
117 n->left = n->right = 0;
118 n->key = key;
119 n->value = value;
120 return n;
121 }
122
_rotate_right(tree_node_t ** pa)123 static void _rotate_right(tree_node_t **pa) {
124 tree_node_t *child;
125 child = (*pa)->left;
126 assert(child);
127 (*pa)->left = child->right;
128 child->right = *pa;
129 *pa = child;
130 }
131
_rotate_left(tree_node_t ** pa)132 static void _rotate_left(tree_node_t **pa) {
133 tree_node_t *child;
134 child = (*pa)->right;
135 assert(child);
136 (*pa)->right = child->left;
137 child->left = *pa;
138 *pa = child;
139 }
140
141 /**
142 * bring this value to the top
143 * */
_splay(IWSTREE * st,int update_if_not_found,tree_node_t ** gpa,tree_node_t ** pa,tree_node_t ** child,const void * key)144 static tree_node_t *_splay(
145 IWSTREE *st,
146 int update_if_not_found,
147 tree_node_t **gpa,
148 tree_node_t **pa,
149 tree_node_t **child,
150 const void *key) {
151
152 int cmp;
153 tree_node_t *next;
154
155 if (!(*child)) {
156 return 0;
157 }
158 cmp = st->cmp((*child)->key, key);
159 if (cmp == 0) {
160 next = *child;
161 } else if (cmp > 0) {
162 next = _splay(st, update_if_not_found, pa, child, &(*child)->left, key);
163 } else {
164 next = _splay(st, update_if_not_found, pa, child, &(*child)->right, key);
165 }
166 if (!next) {
167 if (update_if_not_found) {
168 next = *child;
169 } else {
170 return 0;
171 }
172 } else {
173 if (next != *child) {
174 return next;
175 }
176 }
177
178 if (!pa) {
179 return next;
180 }
181
182 if (!gpa) {
183 /* zig left */
184 if ((*pa)->left == next) {
185 _rotate_right(pa);
186 }
187 /* zig right */
188 else {
189 _rotate_left(pa);
190 }
191 return next;
192 }
193
194 assert(gpa);
195
196 /* zig zig left */
197 if ((*pa)->left == next && (*gpa)->left == *pa) {
198 _rotate_right(pa);
199 _rotate_right(gpa);
200 }
201 /* zig zig right */
202 else if ((*pa)->right == next && (*gpa)->right == *pa) {
203 _rotate_left(pa);
204 _rotate_left(gpa);
205 }
206 /* zig zag right */
207 else if ((*pa)->right == next && (*gpa)->left == *pa) {
208 _rotate_left(pa);
209 _rotate_right(gpa);
210 }
211 /* zig zag left */
212 else if ((*pa)->left == next && (*gpa)->right == *pa) {
213 _rotate_right(pa);
214 _rotate_left(gpa);
215 }
216 return next;
217 }
218
iwstree_is_empty(IWSTREE * st)219 int iwstree_is_empty(IWSTREE *st) {
220 return st->root == 0;
221 }
222
iwstree_remove(IWSTREE * st,const void * key)223 void *iwstree_remove(IWSTREE *st, const void *key) {
224 tree_node_t *root, *tmp;
225 void *val;
226
227 /* make removed node the root */
228 if (!iwstree_get(st, key)) {
229 return 0;
230 }
231 root = st->root;
232 val = root->value;
233
234 assert(0 < st->count);
235 if (root->left == 0) {
236 st->root = root->right;
237 } else {
238 tmp = root->right;
239 st->root = root->left;
240 _splay(st, 1, 0, 0, (tree_node_t **) &st->root, key);
241 ((tree_node_t *) st->root)->right = tmp;
242 }
243 st->count--;
244 assert(root != st->root);
245 free(root);
246 return val;
247 }
248
249 /**
250 * get this item referred to by key. Slap it as root.
251 */
iwstree_get(IWSTREE * st,const void * key)252 void *iwstree_get(IWSTREE *st, const void *key) {
253 tree_node_t *node = _splay(st, 0, 0, 0, (tree_node_t **) &st->root, key);
254 return node ? node->value : 0;
255 }
256
iwstree_count(IWSTREE * st)257 int iwstree_count(IWSTREE *st) {
258 return st->count;
259 }
260
iwstree_peek(IWSTREE * st)261 void *iwstree_peek(IWSTREE *st) {
262 return st->root ? ((tree_node_t *) st->root)->value : 0;
263 }
264
_iwstree_put(IWSTREE * st,void * key,void * value,bool overwrite)265 static iwrc _iwstree_put(IWSTREE *st, void *key, void *value, bool overwrite) {
266 tree_node_t *n;
267 int cmp;
268 if (!st->root) {
269 st->root = _init_node(key, value);
270 if (!st->root) {
271 return iwrc_set_errno(IW_ERROR_ALLOC, errno);
272 }
273 st->count++;
274 return 0;
275 }
276 n = _splay(st, 1, 0, 0, (tree_node_t **) &st->root, key);
277 cmp = st->cmp(((tree_node_t *) st->root)->key, key);
278 if (cmp != 0) {
279 n = _init_node(key, value);
280 if (!n) {
281 return iwrc_set_errno(IW_ERROR_ALLOC, errno);
282 }
283 if (0 < cmp) {
284 n->right = st->root;
285 n->left = n->right->left;
286 n->right->left = 0;
287 } else {
288 n->left = st->root;
289 n->right = n->left->right;
290 n->left->right = 0;
291 }
292 st->count++;
293 } else if (overwrite) {
294 if (n->value && st->kvfree) {
295 st->kvfree(0, n->value);
296 }
297 n->value = value;
298 }
299 st->root = n;
300 return 0;
301 }
302
iwstree_put(IWSTREE * st,void * key,void * value)303 iwrc iwstree_put(IWSTREE *st, void *key, void *value) {
304 return _iwstree_put(st, key, value, false);
305 }
306
iwstree_put_overwrite(IWSTREE * st,void * key,void * value)307 iwrc iwstree_put_overwrite(IWSTREE *st, void *key, void *value) {
308 return _iwstree_put(st, key, value, true);
309 }
310
_iwstree_visit(tree_node_t * n,IWSTREE_VISITOR visitor,void * op)311 static iwrc _iwstree_visit(tree_node_t *n, IWSTREE_VISITOR visitor, void *op) {
312 iwrc rc = 0;
313 if (!visitor(n->key, n->value, op, &rc) || rc) {
314 return rc;
315 }
316 if (n->left) {
317 rc = _iwstree_visit(n->left, visitor, op);
318 RCRET(rc);
319 }
320 if (n->right) {
321 rc = _iwstree_visit(n->right, visitor, op);
322 RCRET(rc);
323 }
324 return rc;
325 }
326
iwstree_visit(IWSTREE * st,IWSTREE_VISITOR visitor,void * op)327 iwrc iwstree_visit(IWSTREE *st, IWSTREE_VISITOR visitor, void *op) {
328 if (st->root) {
329 return _iwstree_visit(st->root, visitor, op);
330 }
331 return 0;
332 }
333
334 #define _ITER_STACK_AUNIT 32
335
_iter_push(IWSTREE_ITER * iter,tree_node_t * n)336 static iwrc _iter_push(IWSTREE_ITER *iter, tree_node_t *n) {
337 if (iter->spos + 1 > iter->slen) {
338 void *np = realloc(iter->stack, (iter->slen + _ITER_STACK_AUNIT) * sizeof(*iter->stack));
339 if (!np) {
340 return iwrc_set_errno(IW_ERROR_ALLOC, errno);
341 }
342 iter->stack = np;
343 iter->slen += _ITER_STACK_AUNIT;
344 }
345 iter->stack[iter->spos] = n;
346 iter->spos++;
347 return 0;
348 }
349
_iter_pop(IWSTREE_ITER * iter)350 static tree_node_t *_iter_pop(IWSTREE_ITER *iter) {
351 if (iter->spos < 1) {
352 return 0;
353 }
354 iter->spos--;
355 return iter->stack[iter->spos];
356 }
357
iwstree_iter_init(IWSTREE * st,IWSTREE_ITER * iter)358 iwrc iwstree_iter_init(IWSTREE *st, IWSTREE_ITER *iter) {
359 memset(iter, 0, sizeof(*iter));
360 iter->st = st;
361 tree_node_t *n = st->root;
362 while (n) {
363 iwrc rc = _iter_push(iter, n);
364 RCRET(rc);
365 n = n->left;
366 }
367 return 0;
368 }
369
iwstree_iter_has_next(IWSTREE_ITER * iter)370 bool iwstree_iter_has_next(IWSTREE_ITER *iter) {
371 return iter->spos > 0;
372 }
373
iwstree_iter_next(IWSTREE_ITER * iter,void ** key,void ** val)374 iwrc iwstree_iter_next(IWSTREE_ITER *iter, void **key, void **val) {
375 if (key) {
376 *key = 0;
377 }
378 if (val) {
379 *val = 0;
380 }
381 if (iter->spos < 1) {
382 return IW_ERROR_NOT_EXISTS;
383 }
384 tree_node_t *n = _iter_pop(iter);
385 assert(n);
386 if (key) {
387 *key = n->key;
388 }
389 if (val) {
390 *val = n->value;
391 }
392 if (n->right) {
393 n = n->right;
394 while (n) {
395 iwrc rc = _iter_push(iter, n);
396 RCRET(rc);
397 n = n->left;
398 }
399 }
400 return 0;
401 }
402
iwstree_iter_close(IWSTREE_ITER * iter)403 void iwstree_iter_close(IWSTREE_ITER *iter) {
404 if (iter->stack) {
405 free(iter->stack);
406 }
407 iter->slen = 0;
408 iter->spos = 0;
409 iter->stack = 0;
410 }
411