summaryrefslogtreecommitdiff
path: root/src/itree.h
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2022-10-02 01:30:44 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2022-10-02 01:30:44 -0400
commit1303f55161ae40cc98ccddc37755b58b68840798 (patch)
treef7fb6040be18969a4b40795f1d5da17056c4bc54 /src/itree.h
parentab2926aad3e15c6cfa0e4b31ae9274c47a58baf2 (diff)
downloademacs-1303f55161ae40cc98ccddc37755b58b68840798.tar.gz
New ITREE_FOREACH macro
* src/itree.h (interval_tree_iter_start): Adjust type. (interval_tree_nodes): Delete declaration. (ITREE_FOREACH, ITREE_FOREACH_ABORT, ITREE_FOREACH_NARROW): New macros. * src/itree.c (interval_tree_contains, interval_tree_insert_gap): Use the new ITREE_FOREACH macro. (interval_tree_nodes): Delete function. (interval_tree_iter_start): Return the iterator. (interval_generator_next, interval_tree_destroy): Don't accept a NULL arg any more. * src/xdisp.c (load_overlay_strings, strings_with_newlines): * src/textprop.c (get_char_property_and_overlay): * src/buffer.c (copy_overlays, delete_all_overlays) (set_overlays_multibyte, swap_buffer_overlays, overlays_in) (next_overlay_change, previous_overlay_change, overlay_touches_p) (overlay_strings, Foverlay_lists, report_overlay_modification) (evaporate_overlays): Use the new ITREE_FOREACH macro. * src/buffer.h (buffer_overlay_iter_start1) (buffer_overlay_iter_start, buffer_overlay_iter_next) (buffer_overlay_iter_finish, buffer_overlay_iter_narrow): Delete declarations.
Diffstat (limited to 'src/itree.h')
-rw-r--r--src/itree.h52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/itree.h b/src/itree.h
index b9294c5662c..1f019a2607e 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -59,6 +59,10 @@ struct interval_tree
struct interval_node *root;
uintmax_t otick; /* offset tick, compared with node's otick. */
intmax_t size; /* Number of nodes in the tree. */
+ /* FIXME: We can only have one iteration active per tree, which is very
+ restrictive. Actually, in practice this is no better than limiting
+ to a single active iteration *globally*, so we could move this `iter`
+ to a global variable! */
struct interval_generator *iter;
};
@@ -79,12 +83,56 @@ void interval_tree_clear (struct interval_tree *);
void interval_tree_insert (struct interval_tree *, struct interval_node *);
bool interval_tree_contains (struct interval_tree *, struct interval_node *);
struct interval_node *interval_tree_remove (struct interval_tree *, struct interval_node *);
-void interval_tree_iter_start (struct interval_tree *, ptrdiff_t, ptrdiff_t, enum interval_tree_order,
+struct interval_generator *interval_tree_iter_start (struct interval_tree *, ptrdiff_t, ptrdiff_t, enum interval_tree_order,
const char* file, int line);
void interval_generator_narrow (struct interval_generator *, ptrdiff_t, ptrdiff_t);
void interval_tree_iter_finish (struct interval_generator *);
struct interval_node *interval_generator_next (struct interval_generator *);
void interval_tree_insert_gap (struct interval_tree *, ptrdiff_t, ptrdiff_t);
void interval_tree_delete_gap (struct interval_tree *, ptrdiff_t, ptrdiff_t);
-void interval_tree_nodes (struct interval_tree *tree, struct interval_node **nodes, enum interval_tree_order order);
+
+/* Iterate over the intervals between BEG and END in the tree T.
+ N will hold successive nodes. ORDER can be one of : `ASCENDING`,
+ `DESCENDING`, or `PRE_ORDER`.
+ It should be used as:
+
+ ITREE_FOREACH (n, t, beg, end, order)
+ {
+ .. do the thing with n ..
+ }
+
+ BEWARE:
+ - The expression T may be evaluated more than once, so make sure
+ it is cheap a pure.
+ - Only a single iteration can happen at a time, so make sure none of the
+ code within the loop can start another tree_itertion.
+ - If you need to exit the loop early, you *have* to call `ITREE_ABORT`
+ just before exiting (e.g. with `break` or `return`).
+ - Non-local exits are not supported within the body of the loop,
+ unless the caller makes sure `ITREE_ABORT` is called via some
+ kind of unwind_protect.
+ - Don't modify the tree during the iteration.
+ */
+#define ITREE_FOREACH(n, t, beg, end, order) \
+ /* FIXME: We'd want to declare `x` right here, but I can't figure out
+ how to make that work here: the `for` syntax only allows a single
+ clause for the var declarations where we need 2 different types.
+ We could use the `struct {foo x; bar y; } p;` trick to declare two
+ vars `p.x` and `p.y` of unrelated types, but then none of the names
+ of the vars matches the `n` we receive :-(. */ \
+ if (!t) \
+ { } \
+ else \
+ for (struct interval_generator *itree_iter_ \
+ = interval_tree_iter_start (t, beg, end, ITREE_##order, \
+ __FILE__, __LINE__); \
+ ((n = interval_generator_next (itree_iter_)) \
+ || (interval_tree_iter_finish (itree_iter_), false));)
+
+#define ITREE_FOREACH_ABORT() \
+ interval_tree_iter_finish (itree_iter_)
+
+#define ITREE_FOREACH_NARROW(beg, end) \
+ interval_generator_narrow (itree_iter_, beg, end)
+
#endif