summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rdxtree.c20
-rw-r--r--rdxtree.h9
-rw-r--r--rdxtree_i.h6
-rw-r--r--test/test_rdxtree.c28
4 files changed, 53 insertions, 10 deletions
diff --git a/rdxtree.c b/rdxtree.c
index cd5750c..c80ac67 100644
--- a/rdxtree.c
+++ b/rdxtree.c
@@ -700,20 +700,24 @@ rdxtree_walk_next(struct rdxtree *tree, struct rdxtree_iter *iter)
return NULL;
if (!rdxtree_entry_is_node(entry)) {
- if (iter->key != 0)
+ if (iter->key != (rdxtree_key_t)-1)
return NULL;
else {
- iter->key = 1;
+ iter->key = 0;
return rdxtree_entry_addr(entry);
}
}
+ key = iter->key + 1;
+
+ if ((key == 0) && (iter->node != NULL))
+ return NULL;
+
root = rdxtree_entry_addr(entry);
restart:
node = root;
height = root->height + 1;
- key = iter->key;
if (key > rdxtree_max_key(height))
return NULL;
@@ -728,7 +732,11 @@ restart:
if (node == NULL) {
shift += RDXTREE_RADIX;
- iter->key = ((key >> shift) + 1) << shift;
+ key = ((key >> shift) + 1) << shift;
+
+ if (key == 0)
+ return NULL;
+
goto restart;
}
@@ -740,7 +748,7 @@ restart:
} while (height > 0);
iter->node = prev;
- iter->key = key + 1;
+ iter->key = key;
return node;
}
@@ -753,7 +761,7 @@ rdxtree_walk(struct rdxtree *tree, struct rdxtree_iter *iter)
if (iter->node == NULL)
return rdxtree_walk_next(tree, iter);
- index = iter->key & RDXTREE_RADIX_MASK;
+ index = (iter->key + 1) & RDXTREE_RADIX_MASK;
if (index != 0) {
orig_index = index;
diff --git a/rdxtree.h b/rdxtree.h
index 5f635f0..9b2a691 100644
--- a/rdxtree.h
+++ b/rdxtree.h
@@ -184,6 +184,15 @@ for (rdxtree_iter_init(iter), ptr = rdxtree_walk(tree, iter); \
ptr = rdxtree_walk(tree, iter))
/*
+ * Return the key of the current pointer from an iterator.
+ */
+static inline rdxtree_key_t
+rdxtree_iter_key(const struct rdxtree_iter *iter)
+{
+ return iter->key;
+}
+
+/*
* Remove all pointers from a tree.
*
* The common way to destroy a tree and its pointers is to loop over all
diff --git a/rdxtree_i.h b/rdxtree_i.h
index 1a72bca..1bd1f64 100644
--- a/rdxtree_i.h
+++ b/rdxtree_i.h
@@ -34,8 +34,8 @@ struct rdxtree {
* Radix tree iterator.
*
* The node member refers to the node containing the current pointer, if any.
- * The key member refers to the key from which to look up the next pointer,
- * in ascending order.
+ * The key member refers to the current pointer, and is valid if and only if
+ * rdxtree_walk() has been called at least once on the iterator.
*/
struct rdxtree_iter {
void *node;
@@ -49,7 +49,7 @@ static inline void
rdxtree_iter_init(struct rdxtree_iter *iter)
{
iter->node = NULL;
- iter->key = 0;
+ iter->key = (rdxtree_key_t)-1;
}
int rdxtree_insert_common(struct rdxtree *tree, rdxtree_key_t key,
diff --git a/test/test_rdxtree.c b/test/test_rdxtree.c
index a92b1b6..69dccee 100644
--- a/test/test_rdxtree.c
+++ b/test/test_rdxtree.c
@@ -144,8 +144,10 @@ destroy_tree(struct rdxtree *tree)
struct rdxtree_iter iter;
struct obj *obj;
- rdxtree_for_each(tree, &iter, obj)
+ rdxtree_for_each(tree, &iter, obj) {
+ assert(obj->id == rdxtree_iter_key(&iter));
obj_destroy(obj);
+ }
rdxtree_remove_all(tree);
}
@@ -1007,6 +1009,29 @@ test_37(void)
}
#endif /* RDXTREE_KEY_32 */
+static void
+test_38(void)
+{
+ struct rdxtree tree;
+ struct obj *obj;
+ int error;
+
+ TITLE("insert 1, 3 and max_key");
+
+ rdxtree_init(&tree);
+ obj = obj_create(1);
+ error = rdxtree_insert(&tree, obj->id, obj);
+ assert(!error);
+ obj = obj_create(3);
+ error = rdxtree_insert(&tree, obj->id, obj);
+ assert(!error);
+ obj = obj_create((rdxtree_key_t)-1);
+ error = rdxtree_insert(&tree, obj->id, obj);
+ assert(!error);
+ print_tree(&tree);
+ destroy_tree(&tree);
+}
+
int
main(int argc, char *argv[])
{
@@ -1054,5 +1079,6 @@ main(int argc, char *argv[])
#ifndef RDXTREE_KEY_32
test_37();
#endif /* RDXTREE_KEY_32 */
+ test_38();
return 0;
}