mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-12 23:46:36 +00:00
Change Semantics of r_rbtree_upper_bound() and simplify Iter Fcns (#15698)
This commit is contained in:
parent
f13802b4f8
commit
2a27daac4c
@ -67,21 +67,18 @@ R_API void r_rbtree_free(RBNode *root, RBNodeFree freefn, void *user);
|
||||
R_API void r_rbtree_insert(RBNode **root, void *data, RBNode *node, RBComparator cmp, void *user);
|
||||
// Return the smallest node that is greater than or equal to `data`
|
||||
R_API RBNode *r_rbtree_lower_bound(RBNode *root, void *data, RBComparator cmp, void *user);
|
||||
// Return the smallest node that is greater than `data`
|
||||
// Return the greatest node that is less than or equal to `data`
|
||||
R_API RBNode *r_rbtree_upper_bound(RBNode *root, void *data, RBComparator cmp, void *user);
|
||||
|
||||
// Create a forward iterator starting from the leftmost node
|
||||
R_API RBIter r_rbtree_first(RBNode *root);
|
||||
// Create a backward iterator starting from the rightmost node
|
||||
R_API RBIter r_rbtree_last(RBNode *root);
|
||||
// Iterate [lower_bound, end) forward, used with r_rbtree_iter_next
|
||||
R_API RBIter r_rbtree_lower_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user);
|
||||
// Iterate [begin, lower_bound) backward, used with r_rbtree_iter_prev
|
||||
|
||||
// Iterate [lower_bound, end] forward, used with r_rbtree_iter_next
|
||||
R_API RBIter r_rbtree_lower_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user);
|
||||
// Iterate [upper_bound, end) forward, used with r_rbtree_iter_next
|
||||
// Iterate [begin, upper_bound] backward, used with r_rbtree_iter_prev
|
||||
R_API RBIter r_rbtree_upper_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user);
|
||||
// Iterate [begin, upper_bound) backward, used with r_rbtree_iter_prev
|
||||
R_API RBIter r_rbtree_upper_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user);
|
||||
|
||||
// struct Node { int key; RBNode rb; };
|
||||
// r_rbtree_iter_get (it, struct Node, rb)
|
||||
|
@ -36,23 +36,30 @@ static inline RBNode *zig_zag(RBNode *x, int dir, RBNodeSum sum) {
|
||||
return z;
|
||||
}
|
||||
|
||||
static inline RBIter bound_iter(RBNode *x, void *data, RBComparator cmp, bool upper, bool backward, void *user) {
|
||||
static inline RBIter bound_iter(RBNode *x, void *data, RBComparator cmp, bool upper, void *user) {
|
||||
RBIter it;
|
||||
it.len = 0;
|
||||
while (x) {
|
||||
int d = cmp (data, x, user);
|
||||
if (upper ? d < 0 : d <= 0) {
|
||||
if (!backward) {
|
||||
|
||||
if (d == 0) {
|
||||
it.path[it.len++] = x;
|
||||
return it;
|
||||
}
|
||||
|
||||
if (d < 0) {
|
||||
if (!upper) {
|
||||
it.path[it.len++] = x;
|
||||
}
|
||||
x = x->child[0];
|
||||
} else {
|
||||
if (backward) {
|
||||
if (upper) {
|
||||
it.path[it.len++] = x;
|
||||
}
|
||||
x = x->child[1];
|
||||
}
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
@ -323,12 +330,8 @@ R_API RBNode *r_rbtree_lower_bound(RBNode *x, void *data, RBComparator cmp, void
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API RBIter r_rbtree_lower_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user) {
|
||||
return bound_iter (root, data, cmp, false, true, user);
|
||||
}
|
||||
|
||||
R_API RBIter r_rbtree_lower_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user) {
|
||||
return bound_iter (root, data, cmp, false, false, user);
|
||||
return bound_iter (root, data, cmp, false, user);
|
||||
}
|
||||
|
||||
R_API RBNode *r_rbtree_upper_bound(RBNode *x, void *data, RBComparator cmp, void *user) {
|
||||
@ -336,9 +339,9 @@ R_API RBNode *r_rbtree_upper_bound(RBNode *x, void *data, RBComparator cmp, void
|
||||
while (x) {
|
||||
int d = cmp (data, x, user);
|
||||
if (d < 0) {
|
||||
ret = x;
|
||||
x = x->child[0];
|
||||
} else {
|
||||
ret = x;
|
||||
x = x->child[1];
|
||||
}
|
||||
}
|
||||
@ -346,11 +349,7 @@ R_API RBNode *r_rbtree_upper_bound(RBNode *x, void *data, RBComparator cmp, void
|
||||
}
|
||||
|
||||
R_API RBIter r_rbtree_upper_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user) {
|
||||
return bound_iter (root, data, cmp, true, true, user);
|
||||
}
|
||||
|
||||
R_API RBIter r_rbtree_upper_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user) {
|
||||
return bound_iter (root, data, cmp, true, false, user);
|
||||
return bound_iter (root, data, cmp, true, user);
|
||||
}
|
||||
|
||||
static RBIter _first(RBNode *x, int dir) {
|
||||
|
@ -80,9 +80,8 @@ bool check(RBNode *tree) {
|
||||
return check1 (tree, 0, 0, true);
|
||||
}
|
||||
|
||||
bool test_r_rbtree_bound(void) {
|
||||
const int key1 = 0x24;
|
||||
struct Node key = {.key = key1};
|
||||
bool test_r_rbtree_bound_iterate() {
|
||||
struct Node key = { 0 };
|
||||
RBIter it;
|
||||
RBNode *tree = NULL;
|
||||
struct Node *x;
|
||||
@ -92,42 +91,83 @@ bool test_r_rbtree_bound(void) {
|
||||
mu_assert_eq (f.len, 0, "iter with 0 length");
|
||||
|
||||
for (i = 0; i < 99; i++) {
|
||||
x = make (i);
|
||||
x = make (i * 2);
|
||||
r_rbtree_insert (&tree, x, &x->rb, cmp, NULL);
|
||||
}
|
||||
|
||||
// lower_bound
|
||||
key.key = 0x24;
|
||||
it = r_rbtree_lower_bound_forward (tree, &key, cmp, NULL);
|
||||
i = key1;
|
||||
i = 0x24;
|
||||
r_rbtree_iter_while (it, x, struct Node, rb) {
|
||||
mu_assert_eq (i, x->key, "lower_bound_forward");
|
||||
i++;
|
||||
mu_assert_eq (x->key, i, "lower_bound_forward equal");
|
||||
i += 2;
|
||||
}
|
||||
it = r_rbtree_lower_bound_backward (tree, &key, cmp, NULL);
|
||||
i = key1 - 1;
|
||||
r_rbtree_iter_while_prev (it, x, struct Node, rb) {
|
||||
mu_assert_eq (i, x->key, "lower_bound_backward");
|
||||
i--;
|
||||
mu_assert_eq (i - 2, 98 * 2, "lower_bound_forward complete");
|
||||
|
||||
key.key = 0x25;
|
||||
it = r_rbtree_lower_bound_forward (tree, &key, cmp, NULL);
|
||||
i = 0x26;
|
||||
r_rbtree_iter_while (it, x, struct Node, rb) {
|
||||
mu_assert_eq (x->key, i, "lower_bound_forward more");
|
||||
i += 2;
|
||||
}
|
||||
mu_assert_eq (i - 2, 98 * 2, "lower_bound_forward complete");
|
||||
|
||||
// upper_bound
|
||||
it = r_rbtree_upper_bound_forward (tree, &key, cmp, NULL);
|
||||
i = key1 + 1;
|
||||
r_rbtree_iter_while (it, x, struct Node, rb) {
|
||||
mu_assert_eq (i, x->key, "upper_bound_forward");
|
||||
i++;
|
||||
}
|
||||
key.key = 0x24;
|
||||
it = r_rbtree_upper_bound_backward (tree, &key, cmp, NULL);
|
||||
i = key1;
|
||||
i = 0x24;
|
||||
r_rbtree_iter_while_prev (it, x, struct Node, rb) {
|
||||
mu_assert_eq (i, x->key, "upper_bound_backward");
|
||||
i--;
|
||||
mu_assert_eq (x->key, i, "upper_bound_backward");
|
||||
i -= 2;
|
||||
}
|
||||
mu_assert_eq (i + 2, 0, "upper_bound_backward complete");
|
||||
|
||||
key.key = 0x25;
|
||||
it = r_rbtree_upper_bound_backward (tree, &key, cmp, NULL);
|
||||
i = 0x24;
|
||||
r_rbtree_iter_while_prev (it, x, struct Node, rb) {
|
||||
mu_assert_eq (x->key, i, "upper_bound_backward less");
|
||||
i -= 2;
|
||||
}
|
||||
mu_assert_eq (i + 2, 0, "upper_bound_backward complete");
|
||||
|
||||
r_rbtree_free (tree, freefn, NULL);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_rbtree_bound() {
|
||||
struct Node key = { 0 };
|
||||
RBIter it;
|
||||
RBNode *tree = NULL;
|
||||
struct Node *x;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 99; i++) {
|
||||
x = make (i*2);
|
||||
r_rbtree_insert (&tree, x, &x->rb, cmp, NULL);
|
||||
}
|
||||
|
||||
key.key = 0x24;
|
||||
x = container_of (r_rbtree_lower_bound (tree, &key, cmp, NULL), struct Node, rb);
|
||||
mu_assert_eq (x->key, 0x24, "lower bound equal");
|
||||
|
||||
key.key = 0x25;
|
||||
x = container_of (r_rbtree_lower_bound (tree, &key, cmp, NULL), struct Node, rb);
|
||||
mu_assert_eq (x->key, 0x26, "lower bound more");
|
||||
|
||||
key.key = 0x24;
|
||||
x = container_of (r_rbtree_upper_bound (tree, &key, cmp, NULL), struct Node, rb);
|
||||
mu_assert_eq (x->key, 0x24, "upper bound equal");
|
||||
|
||||
key.key = 0x25;
|
||||
x = container_of (r_rbtree_upper_bound (tree, &key, cmp, NULL), struct Node, rb);
|
||||
mu_assert_eq (x->key, 0x24, "upper bound less");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool insert_delete(int *a, int n, RBNodeSum sum) {
|
||||
RBNode *tree = NULL;
|
||||
struct Node *x;
|
||||
@ -261,6 +301,7 @@ bool test_r_rbtree_traverse(void) {
|
||||
|
||||
int all_tests() {
|
||||
mu_run_test (test_r_rbtree_bound);
|
||||
mu_run_test (test_r_rbtree_bound_iterate);
|
||||
mu_run_test (test_r_rbtree_insert_delete);
|
||||
mu_run_test (test_r_rbtree_traverse);
|
||||
mu_run_test (test_r_rbtree_augmented_insert_delete);
|
||||
|
Loading…
Reference in New Issue
Block a user