Rizin
unix-like reverse engineering framework and cli tools
rbtree.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2017 MaskRay
2 // SPDX-License-Identifier: BSD-3-Clause
3 
4 #include <stdio.h>
5 
6 #include <rz_util/rz_rbtree.h>
7 #include <rz_util.h>
8 
9 static inline bool red(RBNode *x) {
10  return x && x->red;
11 }
12 
13 static inline RBNode *zag(RBNode *x, int dir, RBNodeSum sum) {
14  RBNode *y = x->child[dir];
15  x->child[dir] = y->child[!dir];
16  y->child[!dir] = x;
17  x->red = true;
18  y->red = false;
19  if (sum) {
20  sum(x);
21  }
22  return y;
23 }
24 
25 static inline RBNode *zig_zag(RBNode *x, int dir, RBNodeSum sum) {
26  RBNode *y = x->child[dir], *z = y->child[!dir];
27  y->child[!dir] = z->child[dir];
28  z->child[dir] = y;
29  x->child[dir] = z->child[!dir];
30  z->child[!dir] = x;
31  x->red = y->red = true;
32  z->red = false;
33  if (sum) {
34  sum(x);
35  sum(y);
36  }
37  return z;
38 }
39 
40 static inline RBIter bound_iter(RBNode *x, void *data, RBComparator cmp, bool upper, void *user) {
41  RBIter it = { 0 };
42  while (x) {
43  int d = cmp(data, x, user);
44 
45  if (d == 0) {
46  it.path[it.len++] = x;
47  return it;
48  }
49 
50  if (d < 0) {
51  if (!upper) {
52  it.path[it.len++] = x;
53  }
54  x = x->child[0];
55  } else {
56  if (upper) {
57  it.path[it.len++] = x;
58  }
59  x = x->child[1];
60  }
61  }
62 
63  return it;
64 }
65 
67 RZ_API bool rz_rbtree_aug_delete(RBNode **root, void *data, RBComparator cmp, void *cmp_user, RBNodeFree freefn, void *free_user, RBNodeSum sum) {
68  RBNode head, *del = NULL, **del_link = NULL, *g = NULL, *p = NULL, *q = &head, *path[RZ_RBTREE_MAX_HEIGHT];
69  int d = 1, d2, dep = 0;
70  head.child[0] = NULL;
71  head.child[1] = *root;
72  while (q->child[d]) {
73  d2 = d;
74  g = p;
75  p = q;
76  if (del_link) {
77  d = 1;
78  } else {
79  d = cmp(data, q->child[d2], cmp_user);
80  if (d < 0) {
81  d = 0;
82  } else if (d > 0) {
83  d = 1;
84  } else {
85  del_link = &q->child[d2];
86  }
87  }
88  if (q != &head) {
89  if (dep >= RZ_RBTREE_MAX_HEIGHT) {
90  RZ_LOG_ERROR("Red-black tree depth is too big\n");
91  break;
92  }
93  path[dep++] = q;
94  }
95  q = q->child[d2];
96  if (q->red || red(q->child[d])) {
97  continue;
98  }
99  if (red(q->child[!d])) {
100  if (del_link && *del_link == q) {
101  del_link = &q->child[!d]->child[d];
102  }
103  p->child[d2] = zag(q, !d, sum);
104  p = p->child[d2];
105  if (dep >= RZ_RBTREE_MAX_HEIGHT) {
106  RZ_LOG_ERROR("Red-black tree depth is too big\n");
107  break;
108  }
109  path[dep++] = p;
110  } else {
111  RBNode *s = p->child[!d2];
112  if (!s) {
113  continue;
114  }
115  if (!red(s->child[0]) && !red(s->child[1])) {
116  p->red = false;
117  q->red = s->red = true;
118  } else {
119  int d3 = g->child[0] != p;
120  RBNode *t;
121  if (red(s->child[d2])) {
122  if (del_link && *del_link == p) {
123  del_link = &s->child[d2]->child[d2];
124  }
125  t = zig_zag(p, !d2, sum);
126  } else {
127  if (del_link && *del_link == p) {
128  del_link = &s->child[d2];
129  }
130  t = zag(p, !d2, sum);
131  }
132  t->red = q->red = true;
133  t->child[0]->red = t->child[1]->red = false;
134  g->child[d3] = t;
135  path[dep - 1] = t;
136  path[dep++] = p;
137  }
138  }
139  }
140  if (del_link) {
141  del = *del_link;
142  p->child[q != p->child[0]] = q->child[q->child[0] == NULL];
143  if (del != q) {
144  *q = *del;
145  *del_link = q;
146  }
147  if (freefn) {
148  freefn(del, free_user);
149  }
150  }
151  if (sum) {
152  while (dep--) {
153  sum(path[dep] == del ? q : path[dep]);
154  }
155  }
156  if ((*root = head.child[1])) {
157  (*root)->red = false;
158  }
159  return del;
160 }
161 
163 RZ_API bool rz_rbtree_aug_insert(RBNode **root, void *data, RBNode *node, RBComparator cmp, void *cmp_user, RBNodeSum sum) {
164  node->child[0] = node->child[1] = NULL;
165  if (!*root) {
166  *root = node;
167  node->red = false;
168  if (sum) {
169  sum(node);
170  }
171  return true;
172  }
173  RBNode *t = NULL, *g = NULL, *p = NULL, *q = *root;
174  int d = 0, dep = 0;
175  bool done = false;
177  for (;;) {
178  if (!q) {
179  q = node;
180  q->red = true;
181  p->child[d] = q;
182  done = true;
183  } else if (red(q->child[0]) && red(q->child[1])) {
184  q->child[0]->red = q->child[1]->red = false;
185  if (q != *root) {
186  q->red = true;
187  }
188  }
189  if (q->red && p && p->red) {
190  int d3 = t ? t->child[0] != g : -1, d2 = g->child[0] != p;
191  if (p->child[d2] == q) {
192  g = zag(g, d2, sum);
193  dep--;
194  path[dep - 1] = g;
195  } else {
196  g = zig_zag(g, d2, sum);
197  dep -= 2;
198  }
199  if (t) {
200  t->child[d3] = g;
201  } else {
202  *root = g;
203  }
204  }
205  if (done) {
206  break;
207  }
208  d = cmp(data, q, cmp_user);
209  t = g;
210  g = p;
211  p = q;
212  if (dep >= RZ_RBTREE_MAX_HEIGHT) {
213  RZ_LOG_ERROR("Red-black tree depth is too big\n");
214  break;
215  }
216  path[dep++] = q;
217  if (d < 0) {
218  d = 0;
219  q = q->child[0];
220  } else {
221  d = 1;
222  q = q->child[1];
223  }
224  }
225  if (sum) {
226  sum(q);
227  while (dep) {
228  sum(path[--dep]);
229  }
230  }
231  return done;
232 }
233 
235 RZ_API bool rz_rbtree_aug_update_sum(RBNode *root, void *data, RBNode *node, RBComparator cmp, void *cmp_user, RBNodeSum sum) {
236  size_t dep = 0;
238  RBNode *cur = root;
239  for (;;) {
240  if (!cur) {
241  return false;
242  }
243  if (dep >= RZ_RBTREE_MAX_HEIGHT) {
244  RZ_LOG_ERROR("Red-black tree depth is too big\n");
245  return false;
246  }
247  path[dep] = cur;
248  dep++;
249  if (cur == node) {
250  break;
251  }
252  int d = cmp(data, cur, cmp_user);
253  cur = cur->child[(d < 0) ? 0 : 1];
254  }
255 
256  for (; dep > 0; dep--) {
257  sum(path[dep - 1]);
258  }
259  return true;
260 }
261 
263 RZ_API bool rz_rbtree_delete(RBNode **root, void *data, RBComparator cmp, void *cmp_user, RBNodeFree freefn, void *free_user) {
264  return rz_rbtree_aug_delete(root, data, cmp, cmp_user, freefn, free_user, NULL);
265 }
266 
267 RZ_API RBNode *rz_rbtree_find(RBNode *x, void *data, RBComparator cmp, void *user) {
268  while (x) {
269  int d = cmp(data, x, user);
270  if (d < 0) {
271  x = x->child[0];
272  } else if (d > 0) {
273  x = x->child[1];
274  } else {
275  return x;
276  }
277  }
278  return NULL;
279 }
280 
282  if (!x) {
283  return;
284  }
285  rz_rbtree_free(x->child[0], freefn, user);
286  rz_rbtree_free(x->child[1], freefn, user);
287  freefn(x, user);
288 }
289 
291 RZ_API bool rz_rbtree_insert(RBNode **root, void *data, RBNode *node, RBComparator cmp, void *user) {
292  return rz_rbtree_aug_insert(root, data, node, cmp, user, NULL);
293 }
294 
296  RBNode *ret = NULL;
297  while (x) {
298  int d = cmp(data, x, user);
299  if (d <= 0) {
300  ret = x;
301  x = x->child[0];
302  } else {
303  x = x->child[1];
304  }
305  }
306  return ret;
307 }
308 
310  return bound_iter(root, data, cmp, false, user);
311 }
312 
314  void *ret = NULL;
315  while (x) {
316  int d = cmp(data, x, user);
317  if (d < 0) {
318  x = x->child[0];
319  } else {
320  ret = x;
321  x = x->child[1];
322  }
323  }
324  return ret;
325 }
326 
328  return bound_iter(root, data, cmp, true, user);
329 }
330 
331 static RBIter _first(RBNode *x, int dir) {
332  RBIter it;
333  it.len = 0;
334  for (; x; x = x->child[dir]) {
335  it.path[it.len++] = x;
336  }
337  return it;
338 }
339 
341  return _first(tree, 0);
342 }
343 
345  return _first(tree, 1);
346 }
347 
348 static inline void _next(RBIter *it, int dir) {
349  RBNode *x = it->path[--it->len];
350  for (x = x->child[!dir]; x; x = x->child[dir]) {
351  it->path[it->len++] = x;
352  }
353 }
354 
356  _next(it, 0);
357 }
358 
360  _next(it, 1);
361 }
362 
364  return RZ_NEW0(RContRBTree);
365 }
366 
369  if (tree) {
370  tree->free = f;
371  }
372  return tree;
373 }
374 
375 typedef struct rcrb_cmp_wrap_t {
378  void *user;
380 
381 static int cont_rbtree_cmp_wrapper(const void *incoming, const RBNode *in_tree, void *user) {
382  RCRBCmpWrap *cmp_wrap = (RCRBCmpWrap *)user;
383  RContRBNode *incoming_node = (RContRBNode *)incoming;
384  RContRBNode *in_tree_node = container_of((RBNode *)in_tree, RContRBNode, node);
385  return cmp_wrap->cmp(incoming_node->data, in_tree_node->data, cmp_wrap->user);
386 }
387 
388 static int cont_rbtree_search_cmp_wrapper(const void *incoming, const RBNode *in_tree, void *user) {
389  RCRBCmpWrap *cmp_wrap = (RCRBCmpWrap *)user;
390  RContRBNode *in_tree_node = container_of((RBNode *)in_tree, RContRBNode, node);
391  return cmp_wrap->cmp((void *)incoming, in_tree_node->data, cmp_wrap->user);
392 }
393 
394 static int cont_rbtree_free_cmp_wrapper(const void *data, const RBNode *in_tree, void *user) {
395  RCRBCmpWrap *cmp_wrap = (RCRBCmpWrap *)user;
396  const int ret = cont_rbtree_cmp_wrapper((void *)data, in_tree, user);
397  if (!ret && cmp_wrap->free) { // this is for deleting
398  RContRBNode *in_tree_node = container_of((void *)in_tree, RContRBNode, node);
399  cmp_wrap->free(in_tree_node->data);
400  }
401  return ret;
402 }
403 
404 RZ_API bool rz_rbtree_cont_insert(RContRBTree *tree, void *data, RContRBCmp cmp, void *user) {
405  rz_return_val_if_fail(tree && cmp, false);
406  if (!tree->root) {
407  tree->root = RZ_NEW0(RContRBNode);
408  if (!tree->root) {
409  RZ_LOG_ERROR("Failed to allocate new red-black tree root\n");
410  return false;
411  }
412  tree->root->data = data;
413  return true;
414  }
415  RContRBNode *incoming_node = RZ_NEW0(RContRBNode);
416  if (!incoming_node) {
417  RZ_LOG_ERROR("Failed to allocate new red-black tree node\n");
418  return false;
419  }
420  incoming_node->data = data;
421  RCRBCmpWrap cmp_wrap = { cmp, NULL, user };
422  RBNode *root_node = &tree->root->node;
423  const bool ret = rz_rbtree_aug_insert(&root_node, incoming_node,
424  &incoming_node->node, cont_rbtree_cmp_wrapper, &cmp_wrap, NULL);
425  if (root_node != (&tree->root->node)) {
426  tree->root = container_of(root_node, RContRBNode, node);
427  }
428  if (!ret) {
429  RZ_LOG_ERROR("Failed to insert new red-black tree node\n");
430  free(incoming_node);
431  }
432  return ret;
433 }
434 
435 static void cont_node_free(RBNode *node, void *user) {
436  RContRBNode *contnode = container_of(node, RContRBNode, node);
437  if (user) {
438  ((RContRBFree)user)(contnode->data);
439  }
440  free(contnode);
441 }
442 
443 RZ_API bool rz_rbtree_cont_delete(RContRBTree *tree, void *data, RContRBCmp cmp, void *user) {
444  if (!(tree && cmp && tree->root)) {
445  return false;
446  }
447  RCRBCmpWrap cmp_wrap = { cmp, tree->free, user };
448  RContRBNode data_wrap = { { { NULL, NULL }, false }, data };
449  RBNode *root_node = &tree->root->node;
450  const bool ret = rz_rbtree_aug_delete(&root_node, &data_wrap, cont_rbtree_free_cmp_wrapper, &cmp_wrap, cont_node_free, NULL, NULL);
451  if (root_node != (&tree->root->node)) {
452  tree->root = container_of(root_node, RContRBNode, node);
453  }
454  return ret;
455 }
456 
457 RZ_API void *rz_rbtree_cont_find(RContRBTree *tree, void *data, RContRBCmp cmp, void *user) {
458  rz_return_val_if_fail(tree && cmp, NULL);
459  if (!tree->root) {
460  return NULL;
461  }
462  RCRBCmpWrap cmp_wrap = { cmp, NULL, user };
463  // RBNode search_node = tree->root->node;
464  RBNode *result_node = rz_rbtree_find(&tree->root->node, data, cont_rbtree_search_cmp_wrapper, &cmp_wrap);
465  if (result_node) {
466  return (container_of(result_node, RContRBNode, node))->data;
467  }
468  return NULL;
469 }
470 
472  if (tree && tree->root) {
473  rz_rbtree_free(&tree->root->node, cont_node_free, tree->free);
474  }
475  free(tree);
476 }
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:942
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
int root
Definition: enough.c:226
struct @667 g
struct tab * done
Definition: enough.c:233
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static void freefn(HtName_(Ht) *ht, HT_(Kv) *kv)
Definition: ht_inc.c:46
void * p
Definition: libc.cpp:67
static void del(RzAnalysis *a, RzAnalysisMetaType type, const RzSpace *space, ut64 addr, ut64 size)
Definition: meta.c:155
int x
Definition: mipsasm.c:20
RZ_API RBIter rz_rbtree_last(RBNode *tree)
Definition: rbtree.c:344
RZ_API RZ_OWN RContRBTree * rz_rbtree_cont_newf(RContRBFree f)
Definition: rbtree.c:367
RZ_API bool rz_rbtree_cont_delete(RContRBTree *tree, void *data, RContRBCmp cmp, void *user)
Definition: rbtree.c:443
RZ_API RBNode * rz_rbtree_upper_bound(RBNode *x, void *data, RBComparator cmp, void *user)
Definition: rbtree.c:313
RZ_API void rz_rbtree_cont_free(RContRBTree *tree)
Definition: rbtree.c:471
static RBNode * zig_zag(RBNode *x, int dir, RBNodeSum sum)
Definition: rbtree.c:25
RZ_API bool rz_rbtree_insert(RBNode **root, void *data, RBNode *node, RBComparator cmp, void *user)
Returns true if the node was inserted successfully.
Definition: rbtree.c:291
RZ_API RBNode * rz_rbtree_lower_bound(RBNode *x, void *data, RBComparator cmp, void *user)
Definition: rbtree.c:295
RZ_API bool rz_rbtree_aug_update_sum(RBNode *root, void *data, RBNode *node, RBComparator cmp, void *cmp_user, RBNodeSum sum)
Returns true if the sum has been updated, false if node has not been found.
Definition: rbtree.c:235
static void cont_node_free(RBNode *node, void *user)
Definition: rbtree.c:435
RZ_API bool rz_rbtree_delete(RBNode **root, void *data, RBComparator cmp, void *cmp_user, RBNodeFree freefn, void *free_user)
Returns true if a node with an equal key is deleted.
Definition: rbtree.c:263
static RBIter _first(RBNode *x, int dir)
Definition: rbtree.c:331
RZ_API bool rz_rbtree_cont_insert(RContRBTree *tree, void *data, RContRBCmp cmp, void *user)
Definition: rbtree.c:404
static int cont_rbtree_cmp_wrapper(const void *incoming, const RBNode *in_tree, void *user)
Definition: rbtree.c:381
RZ_API void rz_rbtree_free(RZ_NULLABLE RBNode *x, RBNodeFree freefn, void *user)
Definition: rbtree.c:281
RZ_API bool rz_rbtree_aug_delete(RBNode **root, void *data, RBComparator cmp, void *cmp_user, RBNodeFree freefn, void *free_user, RBNodeSum sum)
Returns true if a node with an equal key is deleted.
Definition: rbtree.c:67
static bool red(RBNode *x)
Definition: rbtree.c:9
RZ_API RBIter rz_rbtree_lower_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user)
Definition: rbtree.c:309
RZ_API RBNode * rz_rbtree_find(RBNode *x, void *data, RBComparator cmp, void *user)
Definition: rbtree.c:267
static RBNode * zag(RBNode *x, int dir, RBNodeSum sum)
Definition: rbtree.c:13
RZ_API void * rz_rbtree_cont_find(RContRBTree *tree, void *data, RContRBCmp cmp, void *user)
Definition: rbtree.c:457
RZ_API RBIter rz_rbtree_first(RBNode *tree)
Definition: rbtree.c:340
RZ_API RZ_OWN RContRBTree * rz_rbtree_cont_new(void)
Definition: rbtree.c:363
RZ_API void rz_rbtree_iter_next(RBIter *it)
Definition: rbtree.c:355
static int cont_rbtree_free_cmp_wrapper(const void *data, const RBNode *in_tree, void *user)
Definition: rbtree.c:394
static RBIter bound_iter(RBNode *x, void *data, RBComparator cmp, bool upper, void *user)
Definition: rbtree.c:40
RZ_API void rz_rbtree_iter_prev(RBIter *it)
Definition: rbtree.c:359
static int cont_rbtree_search_cmp_wrapper(const void *incoming, const RBNode *in_tree, void *user)
Definition: rbtree.c:388
static void _next(RBIter *it, int dir)
Definition: rbtree.c:348
RZ_API bool rz_rbtree_aug_insert(RBNode **root, void *data, RBNode *node, RBComparator cmp, void *cmp_user, RBNodeSum sum)
Returns true if the node was inserted successfully.
Definition: rbtree.c:163
struct rcrb_cmp_wrap_t RCRBCmpWrap
RZ_API RBIter rz_rbtree_upper_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user)
Definition: rbtree.c:327
static RzSocket * s
Definition: rtr.c:28
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
void(* RContRBFree)(void *)
Definition: rz_rbtree.h:47
void(* RBNodeFree)(RBNode *node, void *user)
Definition: rz_rbtree.h:31
void(* RBNodeSum)(RBNode *node)
Definition: rz_rbtree.h:32
#define RZ_RBTREE_MAX_HEIGHT
Definition: rz_rbtree.h:16
int(* RContRBCmp)(void *incoming, void *in, void *user)
Definition: rz_rbtree.h:46
int(* RBComparator)(const void *incoming, const RBNode *in_tree, void *user)
Definition: rz_rbtree.h:29
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define container_of(ptr, type, member)
Definition: rz_types.h:650
#define d(i)
Definition: sha256.c:44
#define f(i)
Definition: sha256.c:46
RContRBCmp cmp
Definition: rbtree.c:376
void * user
Definition: rbtree.c:378
RContRBFree free
Definition: rbtree.c:377
RContRBNode * root
Definition: rz_rbtree.h:54
RBNode * path[RZ_RBTREE_MAX_HEIGHT]
Definition: rz_rbtree.h:43
struct rz_rb_node_t * child[2]
Definition: rz_rbtree.h:20