diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-10-02 01:30:44 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-10-02 01:30:44 -0400 |
commit | 1303f55161ae40cc98ccddc37755b58b68840798 (patch) | |
tree | f7fb6040be18969a4b40795f1d5da17056c4bc54 /src/itree.h | |
parent | ab2926aad3e15c6cfa0e4b31ae9274c47a58baf2 (diff) | |
download | emacs-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.h | 52 |
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 |