summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/btree_test.c26
-rw-r--r--zix/btree.c11
2 files changed, 34 insertions, 3 deletions
diff --git a/test/btree_test.c b/test/btree_test.c
index 93a257f..c45b3e9 100644
--- a/test/btree_test.c
+++ b/test/btree_test.c
@@ -1,5 +1,5 @@
/*
- Copyright 2011-2014 David Robillard <http://drobilla.net>
+ Copyright 2011-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -324,7 +324,7 @@ stress(int test_num, size_t n_elems)
}
// Delete some elements in a random order
- for (size_t e = 0; e < zix_btree_size(t); e++) {
+ for (size_t e = 0; e < zix_btree_size(t) / 2; e++) {
r = ith_elem(test_num, n_elems, rand() % n_elems);
uintptr_t removed;
ZixStatus rst = zix_btree_remove(t, (void*)r, (void**)&removed, &next);
@@ -335,6 +335,28 @@ stress(int test_num, size_t n_elems)
zix_btree_iter_free(next);
next = NULL;
+ // Delete all remaining elements via next iterator
+ next = zix_btree_begin(t);
+ uintptr_t last_value = 0;
+ while (!zix_btree_iter_is_end(next)) {
+ const uintptr_t value = (uintptr_t)zix_btree_get(next);
+ uintptr_t removed = 0;
+ if (zix_btree_remove(t, zix_btree_get(next), (void**)&removed, &next)) {
+ return test_fail(t, "Error removing next item %lu\n", (uintptr_t)r);
+ } else if (removed != value) {
+ return test_fail(t, "Removed wrong next item %lu != %lu\n",
+ removed, (uintptr_t)value);
+ } else if (removed < last_value) {
+ return test_fail(t, "Removed unordered next item %lu < %lu\n",
+ removed, (uintptr_t)value);
+ }
+
+ last_value = removed;
+ }
+ assert(!next || zix_btree_size(t) == 0);
+ zix_btree_iter_free(next);
+ next = NULL;
+
zix_btree_free(t);
// Test lower_bound with wildcard comparator
diff --git a/zix/btree.c b/zix/btree.c
index b5e4b88..de5d777 100644
--- a/zix/btree.c
+++ b/zix/btree.c
@@ -1,5 +1,5 @@
/*
- Copyright 2011-2014 David Robillard <http://drobilla.net>
+ Copyright 2011-2019 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -557,6 +557,15 @@ zix_btree_remove(ZixBTree* const t,
!zix_btree_node_is_minimal(n->children[i + 1])) {
// Steal a key from child's right sibling
n = zix_btree_rotate_left(n, i);
+ } else if (n == t->root && n->n_vals == 1) {
+ // Root has two children, both minimal, delete it
+ assert(i == 0 || i == 1);
+ const uint16_t counts[2] = {n->children[0]->n_vals,
+ n->children[1]->n_vals};
+
+ n = zix_btree_merge(t, n, 0);
+ ti->stack[ti->level].node = n;
+ ti->stack[ti->level].index = counts[i];
} else {
// Both child's siblings are minimal, merge them
if (i < n->n_vals) {