• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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