Rizin
unix-like reverse engineering framework and cli tools
tree.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2007-2015 ret2libc <sirmy15@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_util.h>
5 #include <rz_vector.h>
6 
7 static void tree_dfs_node(RTreeNode *r, RTreeVisitor *vis) {
8  RzStack *s;
9  RzListIter *it;
10  RTreeNode *n;
11 
12  s = rz_stack_new(16);
13  if (!s) {
14  return;
15  }
16  rz_stack_push(s, r);
17  while (!rz_stack_is_empty(s)) {
19 
20  if (vis->pre_visit) {
21  vis->pre_visit(el, vis);
22  }
23 
24  rz_list_foreach_prev(el->children, it, n) {
25  if (vis->discover_child) {
26  vis->discover_child(n, vis);
27  }
28  rz_stack_push(s, n);
29  }
30 
31  if (vis->post_visit) {
32  vis->post_visit(el, vis);
33  }
34  }
35 
37 }
38 
39 static void rz_tree_node_free(RTreeNode *n) {
40  rz_list_free(n->children);
41  if (n->free) {
42  n->free(n->data);
43  }
44  free(n);
45 }
46 
47 static void node_free(RTreeNode *n, RTreeVisitor *vis) {
49 }
50 
51 static void free_all_children(RTree *t) {
52  RTreeVisitor vis = { 0 };
54  rz_tree_bfs(t, &vis);
55 }
56 
57 static void update_depth(RTreeNode *n, RTreeVisitor *vis) {
58  n->depth = n->parent ? n->parent->depth + 1 : 0;
59 }
60 
61 static RTreeNode *node_new(RTree *t, void *data) {
63  if (!n) {
64  return NULL;
65  }
66  n->children = rz_list_new();
67  n->data = data;
68  n->tree = t;
69  return n;
70 }
71 
73  return RZ_NEW0(RTree);
74 }
75 
77  if (!t) {
78  return;
79  }
80 
82  free(t);
83 }
84 
86  if (!t) {
87  return;
88  }
89 
91  t->root = NULL;
92 }
93 
94 /* add a node in the RTree t as a child of the RTreeNode node.
95  * NOTE: the first call to this function, should add the root
96  * of the tree so the node will be NULL. */
97 /* TODO: allow to replace the root of the tree and make it a child of the new
98  * node */
99 RZ_API RTreeNode *rz_tree_add_node(RTree *t, RTreeNode *node, void *child_data) {
100  RTreeNode *child;
101  RTreeVisitor vis = { 0 };
102 
103  /* a NULL node is allowed only the first time, to set the root */
104  if (!t || (node && node->tree != t) || (t->root && !node)) {
105  return NULL;
106  }
107 
108  child = node_new(t, child_data);
109  if (!node && !t->root) {
110  t->root = child;
111  } else if (node) {
112  rz_list_append(node->children, child);
113  node->n_children++;
114  }
115  child->parent = node;
116 
117  /* update depth */
119  tree_dfs_node(child, &vis);
120 
121  return child;
122 }
123 
125  if (!t || !t->root) {
126  return;
127  }
128 
129  tree_dfs_node(t->root, vis);
130 }
131 
133  if (!t || !t->root) {
134  return;
135  }
136 
138  if (!pv) {
139  return;
140  }
141  rz_pvector_reserve(pv, 16);
142  rz_pvector_push(pv, t->root);
143  while (!rz_pvector_empty(pv)) {
145  if (!el) {
146  break;
147  }
148  RTreeNode *n;
149  RzListIter *it;
150 
151  if (vis->pre_visit) {
152  vis->pre_visit(el, vis);
153  }
154 
155  rz_list_foreach (el->children, it, n) {
156  if (vis->discover_child) {
157  vis->discover_child(n, vis);
158  }
159  rz_pvector_push(pv, n);
160  }
161 
162  if (vis->post_visit) {
163  vis->post_visit(el, vis);
164  }
165  }
166 
167  rz_pvector_free(pv);
168 }
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static void free_all_children(RTree *t)
Definition: tree.c:51
static void node_free(RTreeNode *n, RTreeVisitor *vis)
Definition: tree.c:47
RZ_API RTreeNode * rz_tree_add_node(RTree *t, RTreeNode *node, void *child_data)
Definition: tree.c:99
RZ_API void rz_tree_reset(RTree *t)
Definition: tree.c:85
RZ_API void rz_tree_free(RTree *t)
Definition: tree.c:76
RZ_API void rz_tree_bfs(RTree *t, RTreeVisitor *vis)
Definition: tree.c:132
static void tree_dfs_node(RTreeNode *r, RTreeVisitor *vis)
Definition: tree.c:7
static RTreeNode * node_new(RTree *t, void *data)
Definition: tree.c:61
RZ_API RTree * rz_tree_new(void)
Definition: tree.c:72
RZ_API void rz_tree_dfs(RTree *t, RTreeVisitor *vis)
Definition: tree.c:124
static void update_depth(RTreeNode *n, RTreeVisitor *vis)
Definition: tree.c:57
static void rz_tree_node_free(RTreeNode *n)
Definition: tree.c:39
int n
Definition: mipsasm.c:19
static RzSocket * s
Definition: rtr.c:28
RZ_API bool rz_stack_is_empty(RzStack *s)
Definition: stack.c:68
RZ_API void * rz_stack_pop(RzStack *s)
Definition: stack.c:59
RZ_API bool rz_stack_push(RzStack *s, void *el)
Definition: stack.c:42
RZ_API RzStack * rz_stack_new(ut32 n)
Definition: stack.c:6
RZ_API void rz_stack_free(RzStack *s)
Definition: stack.c:29
void(* RTreeNodeVisitCb)(RTreeNode *n, RTreeVisitor *vis)
Definition: rz_tree.h:27
#define RZ_NEW0(x)
Definition: rz_types.h:284
static void ** rz_pvector_reserve(RzPVector *vec, size_t capacity)
Definition: rz_vector.h:312
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void * rz_pvector_pop_front(RzPVector *vec)
Definition: vector.c:379
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
unsigned int n_children
Definition: rz_tree.h:11
struct rz_tree_node_t * parent
Definition: rz_tree.h:8
struct rz_tree_t * tree
Definition: rz_tree.h:9
RzList * children
Definition: rz_tree.h:10
RTreeNode * root
Definition: rz_tree.h:18
void(* discover_child)(RTreeNode *, struct rz_tree_visitor_t *)
Definition: rz_tree.h:24
void(* pre_visit)(RTreeNode *, struct rz_tree_visitor_t *)
Definition: rz_tree.h:22
void(* post_visit)(RTreeNode *, struct rz_tree_visitor_t *)
Definition: rz_tree.h:23