aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLionel Landwerlin <[email protected]>2018-07-29 14:13:25 +0100
committerLionel Landwerlin <[email protected]>2018-08-22 17:49:36 +0100
commit14a1cb37ebd3adbceb56f99f4727e45309b75ec2 (patch)
tree2dffb0f566eece202ed5920df907fced4f803736
parent4616639b49b4bbc91e503c1c27632dccc1c2b5be (diff)
util: rb_tree: add safe iterators
v2: Add helper to make iterators more readable (Rafael) Fix rev iterator bug (Rafael) Signed-off-by: Lionel Landwerlin <[email protected]> Reviewed-by: Rafael Antognolli <[email protected]>
-rw-r--r--src/util/rb_tree.h58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/util/rb_tree.h b/src/util/rb_tree.h
index c77e9255ea2..1e8aeb4a7b2 100644
--- a/src/util/rb_tree.h
+++ b/src/util/rb_tree.h
@@ -227,6 +227,30 @@ struct rb_node *rb_node_next(struct rb_node *node);
/** Get the next previous (to the left) in the tree or NULL */
struct rb_node *rb_node_prev(struct rb_node *node);
+/** Get the next node if available or the same node again.
+ *
+ * \param type The type of the containing data structure
+ *
+ * \param node The variable name for current node in the iteration;
+ * this will be declared as a pointer to \p type
+ *
+ * \param field The rb_node field in containing data structure
+ */
+#define rb_tree_node_next_if_available(type, node, field) \
+ (&node->field != NULL) ? rb_node_data(type, rb_node_next(&node->field), field) : node
+
+/** Get the previous node if available or the same node again.
+ *
+ * \param type The type of the containing data structure
+ *
+ * \param node The variable name for current node in the iteration;
+ * this will be declared as a pointer to \p type
+ *
+ * \param field The rb_node field in containing data structure
+ */
+#define rb_tree_node_prev_if_available(type, node, field) \
+ (&node->field != NULL) ? rb_node_data(type, rb_node_prev(&node->field), field) : node
+
/** Iterate over the nodes in the tree
*
* \param type The type of the containing data structure
@@ -243,6 +267,23 @@ struct rb_node *rb_node_prev(struct rb_node *node);
&node->field != NULL; \
node = rb_node_data(type, rb_node_next(&node->field), field))
+/** Iterate over the nodes in the tree, allowing the current node to be freed
+ *
+ * \param type The type of the containing data structure
+ *
+ * \param node The variable name for current node in the iteration;
+ * this will be declared as a pointer to \p type
+ *
+ * \param T The red-black tree
+ *
+ * \param field The rb_node field in containing data structure
+ */
+#define rb_tree_foreach_safe(type, node, T, field) \
+ for (type *node = rb_node_data(type, rb_tree_first(T), field), \
+ *__next = rb_tree_node_next_if_available(type, node, field); \
+ &node->field != NULL; \
+ node = __next, __next = rb_tree_node_next_if_available(type, node, field))
+
/** Iterate over the nodes in the tree in reverse
*
* \param type The type of the containing data structure
@@ -259,6 +300,23 @@ struct rb_node *rb_node_prev(struct rb_node *node);
&node->field != NULL; \
node = rb_node_data(type, rb_node_prev(&node->field), field))
+/** Iterate over the nodes in the tree in reverse, allowing the current node to be freed
+ *
+ * \param type The type of the containing data structure
+ *
+ * \param node The variable name for current node in the iteration;
+ * this will be declared as a pointer to \p type
+ *
+ * \param T The red-black tree
+ *
+ * \param field The rb_node field in containing data structure
+ */
+#define rb_tree_foreach_rev_safe(type, node, T, field) \
+ for (type *node = rb_node_data(type, rb_tree_last(T), field), \
+ *__prev = rb_tree_node_prev_if_available(type, node, field); \
+ &node->field != NULL; \
+ node = __prev, __prev = rb_tree_node_prev_if_available(type, node, field))
+
/** Validate a red-black tree
*
* This function walks the tree and validates that this is a valid red-