Implement r_rbtree_cont_node_prev (siol eternal) ##util

This commit is contained in:
condret 2021-03-16 15:46:25 +01:00
parent a3e3b5af7c
commit 3f96c6fda6
3 changed files with 53 additions and 1 deletions

View File

@ -112,6 +112,7 @@ R_API bool r_rbtree_cont_insert(RContRBTree *tree, void *data, RContRBCmp cmp, v
R_API bool r_rbtree_cont_delete(RContRBTree *tree, void *data, RContRBCmp cmp, void *user);
R_API RContRBNode *r_rbtree_cont_find_node(RContRBTree *tree, void *data, RContRBCmp cmp, void *user);
R_API RContRBNode *r_rbtree_cont_node_next(RContRBNode *node);
R_API RContRBNode *r_rbtree_cont_node_prev(RContRBNode *node);
R_API void *r_rbtree_cont_find(RContRBTree *tree, void *data, RContRBCmp cmp, void *user);
R_API void *r_rbtree_cont_first(RContRBTree *tree);
R_API void *r_rbtree_cont_last(RContRBTree *tree);

View File

@ -540,6 +540,33 @@ R_API RContRBNode *r_rbtree_cont_node_next(RContRBNode *node) {
return (container_of (parent, RContRBNode, node));
}
R_API RContRBNode *r_rbtree_cont_node_prev(RContRBNode *node) {
r_return_val_if_fail (node, NULL);
RBNode *_node = &node->node;
if (_node->child[0]) {
_node = _node->child[0];
// next node is the most right child-node of the left subtree
// rightsided walk down that subtree until there is no more right child
while (_node->child[1]) {
_node = _node->child[1];
}
return (container_of (_node, RContRBNode, node));
}
RBNode *parent = _node->parent;
if (!parent) {
return NULL;
}
// walk up the tree, until _node is no longer left child of it's parent
while (parent->child[0] == _node) {
_node = parent;
parent = _node->parent;
if (!parent) {
return NULL;
}
}
return (container_of (parent, RContRBNode, node));
}
// not a direct pendant to r_rbtree_first, but similar
// returns first element in the tree, not an iter or a node
R_API void *r_rbtree_cont_first(RContRBTree *tree) {

View File

@ -94,11 +94,35 @@ bool test_r_rbtree_cont_node_next() {
}
mu_assert ("rbtree_cont_node_next", ret);
mu_end;
}
}
bool test_r_rbtree_cont_node_prev() {
RContRBTree *tree = r_rbtree_cont_new ();
ut32 i;
for (i = 0; i < 100; i++) {
ut32 v = (ut32)r_num_rand (UT32_MAX >> 1);
r_rbtree_cont_insert (tree, (void *)(size_t)v, simple_cmp, NULL);
}
bool ret = true;
void *v = r_rbtree_cont_last (tree);
RContRBNode *node = r_rbtree_cont_find_node (tree, v, simple_cmp, NULL);
i = (ut32)(size_t)v;
node = r_rbtree_cont_node_prev (node);
mu_assert ("rbtree_cont_node_prev no node befor last", !!node);
while (node) {
const ut32 prev = (ut32)(size_t)node->data;
ret &= (i >= prev);
i = prev;
node = r_rbtree_cont_node_prev (node);
}
mu_assert ("rbtree_cont_node_prev", ret);
mu_end;
}
int main(int argc, char *argv[]) {
mu_run_test (test_r_rbtree_cont_insert);
mu_run_test (test_r_rbtree_cont_delete);
mu_run_test (test_r_rbtree_cont_node_next);
mu_run_test (test_r_rbtree_cont_node_prev);
return tests_run != tests_passed;
}