aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2022-10-02 11:11:57 -0400
committerStefan Monnier2022-10-02 11:11:57 -0400
commitba5fe8e7895a2cbfd2d666ca88c0ed96a73fbe29 (patch)
tree86ef32619bf43d7636281a565d6168a3025ee60f /src
parentc3eb6c0563cc95b2134af9fe0ee6f304ddbb0480 (diff)
downloademacs-ba5fe8e7895a2cbfd2d666ca88c0ed96a73fbe29.tar.gz
emacs-ba5fe8e7895a2cbfd2d666ca88c0ed96a73fbe29.zip
itree.c: Remove `tree` field from iterator
* src/itree.c (interval_generator_ensure_space, interval_generator_reset): Inline and then delete functions. (interval_tree_inherit_offset): Only take the tree's `otick` as arg. Update all callers. (struct interval_generator): Remove `tree` field, replace with a copy of the tree's `otick`. (interval_stack_push_flagged): The arg should be a real node. (interval_tree_insert_gap): Prefer checking root==NULL rather than size==0. Skip loop when tree is empty to avoid pushing&processing the NULL node. (interval_tree_inherit_offset): Prefer parent==NULL rather than node==root to avoid accessing the tree object.
Diffstat (limited to 'src')
-rw-r--r--src/itree.c151
1 files changed, 67 insertions, 84 deletions
diff --git a/src/itree.c b/src/itree.c
index eeecaf1839a..1ce45a981eb 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -98,11 +98,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
98 inconsistently/interchangeably. We should fix this naming. */ 98 inconsistently/interchangeably. We should fix this naming. */
99 99
100static struct interval_node *interval_tree_validate (struct interval_tree *, struct interval_node *); 100static struct interval_node *interval_tree_validate (struct interval_tree *, struct interval_node *);
101static void interval_generator_ensure_space (struct interval_generator *);
102static bool interval_node_intersects (const struct interval_node *, ptrdiff_t, ptrdiff_t); 101static bool interval_node_intersects (const struct interval_node *, ptrdiff_t, ptrdiff_t);
103static int interval_tree_max_height (const struct interval_tree *); 102static int interval_tree_max_height (const struct interval_tree *);
104static void interval_tree_update_limit (const struct interval_tree *, struct interval_node *); 103static void interval_tree_update_limit (const struct interval_tree *, struct interval_node *);
105static void interval_tree_inherit_offset (const struct interval_tree *, struct interval_node *); 104static void interval_tree_inherit_offset (uintmax_t otick, struct interval_node *);
106static void interval_tree_propagate_limit (const struct interval_tree *, struct interval_node *); 105static void interval_tree_propagate_limit (const struct interval_tree *, struct interval_node *);
107static void interval_tree_rotate_left (struct interval_tree *, struct interval_node *); 106static void interval_tree_rotate_left (struct interval_tree *, struct interval_node *);
108static void interval_tree_rotate_right (struct interval_tree *, struct interval_node *); 107static void interval_tree_rotate_right (struct interval_tree *, struct interval_node *);
@@ -112,9 +111,6 @@ static void interval_tree_transplant (struct interval_tree *, struct interval_no
112static struct interval_node *interval_tree_subtree_min (const struct interval_tree *, struct interval_node *); 111static struct interval_node *interval_tree_subtree_min (const struct interval_tree *, struct interval_node *);
113static struct interval_generator* interval_generator_create (struct interval_tree *); 112static struct interval_generator* interval_generator_create (struct interval_tree *);
114static void interval_generator_destroy (struct interval_generator *); 113static void interval_generator_destroy (struct interval_generator *);
115static void interval_generator_reset (struct interval_generator *,
116 ptrdiff_t, ptrdiff_t,
117 enum interval_tree_order);
118static inline void interval_tree_iter_ensure_space (struct interval_tree *); 114static inline void interval_tree_iter_ensure_space (struct interval_tree *);
119 115
120/* The sentinel node, the null node. */ 116/* The sentinel node, the null node. */
@@ -142,10 +138,10 @@ struct interval_stack
142/* State used when iterating interval. */ 138/* State used when iterating interval. */
143struct interval_generator 139struct interval_generator
144{ 140{
145 struct interval_tree *tree;
146 struct interval_stack *stack; 141 struct interval_stack *stack;
147 ptrdiff_t begin; 142 ptrdiff_t begin;
148 ptrdiff_t end; 143 ptrdiff_t end;
144 uintmax_t otick; /* A copy of the tree's `otick`. */
149 enum interval_tree_order order; 145 enum interval_tree_order order;
150 bool_bf running : 1; 146 bool_bf running : 1;
151 const char* file; 147 const char* file;
@@ -222,6 +218,8 @@ static inline void
222interval_stack_push_flagged (struct interval_stack *stack, 218interval_stack_push_flagged (struct interval_stack *stack,
223 struct interval_node *node, bool flag) 219 struct interval_node *node, bool flag)
224{ 220{
221 eassert (node && node != ITREE_NULL);
222
225 /* FIXME: This call to `interval_stack_ensure_space` is a bit redundant 223 /* FIXME: This call to `interval_stack_ensure_space` is a bit redundant
226 with the work of `interval_generator_ensure_space` but it's still needed 224 with the work of `interval_generator_ensure_space` but it's still needed
227 here because `interval_generator_next` can push up to 3 elements per 225 here because `interval_generator_next` can push up to 3 elements per
@@ -450,7 +448,7 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
450 448
451 struct interval_node *broken = NULL; 449 struct interval_node *broken = NULL;
452 450
453 interval_tree_inherit_offset (tree, node); 451 interval_tree_inherit_offset (tree->otick, node);
454 if (node->left == ITREE_NULL || node->right == ITREE_NULL) 452 if (node->left == ITREE_NULL || node->right == ITREE_NULL)
455 { 453 {
456 struct interval_node *subst 454 struct interval_node *subst
@@ -475,7 +473,7 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
475 min->right = node->right; 473 min->right = node->right;
476 min->right->parent = min; 474 min->right->parent = min;
477 } 475 }
478 interval_tree_inherit_offset (tree, min); 476 interval_tree_inherit_offset (tree->otick, min);
479 interval_tree_transplant (tree, min, node); 477 interval_tree_transplant (tree, min, node);
480 min->left = node->left; 478 min->left = node->left;
481 min->left->parent = min; 479 min->left->parent = min;
@@ -504,7 +502,7 @@ interval_tree_validate (struct interval_tree *tree, struct interval_node *node)
504 if (node != tree->root) 502 if (node != tree->root)
505 interval_tree_validate (tree, node->parent); 503 interval_tree_validate (tree, node->parent);
506 504
507 interval_tree_inherit_offset (tree, node); 505 interval_tree_inherit_offset (tree->otick, node);
508 return node; 506 return node;
509} 507}
510 508
@@ -527,10 +525,16 @@ interval_tree_iter_start (struct interval_tree *tree,
527 iter->file, iter->line, file, line); 525 iter->file, iter->line, file, line);
528 emacs_abort (); 526 emacs_abort ();
529 } 527 }
530 interval_generator_reset (iter, begin, end, order); 528 iter->begin = begin;
531 iter->running = true; 529 iter->end = end;
530 iter->otick = tree->otick;
531 iter->order = order;
532 interval_stack_clear (iter->stack);
533 if (begin <= end && tree->root != ITREE_NULL)
534 interval_stack_push_flagged (iter->stack, tree->root, false);
532 iter->file = file; 535 iter->file = file;
533 iter->line = line; 536 iter->line = line;
537 iter->running = true;
534 return iter; 538 return iter;
535} 539}
536 540
@@ -549,7 +553,8 @@ interval_tree_iter_finish (struct interval_generator *iter)
549static inline void 553static inline void
550interval_tree_iter_ensure_space (struct interval_tree *tree) 554interval_tree_iter_ensure_space (struct interval_tree *tree)
551{ 555{
552 interval_generator_ensure_space (tree->iter); 556 interval_stack_ensure_space (tree->iter->stack,
557 interval_tree_max_height (tree) + 1);
553} 558}
554 559
555static int 560static int
@@ -570,7 +575,7 @@ interval_tree_max_height (const struct interval_tree *tree)
570void 575void
571interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length) 576interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length)
572{ 577{
573 if (length <= 0 || tree->size == 0) 578 if (length <= 0 || tree->root == ITREE_NULL)
574 return; 579 return;
575 580
576 /* FIXME: Don't allocate generator/stack anew every time. */ 581 /* FIXME: Don't allocate generator/stack anew every time. */
@@ -588,45 +593,48 @@ interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t l
588 for (int i = 0; i < saved->length; ++i) 593 for (int i = 0; i < saved->length; ++i)
589 interval_tree_remove (tree, nav_nodeptr (saved->nodes[i])); 594 interval_tree_remove (tree, nav_nodeptr (saved->nodes[i]));
590 595
591
592 /* We can't use a generator here, because we can't effectively 596 /* We can't use a generator here, because we can't effectively
593 narrow AND shift some subtree at the same time. */ 597 narrow AND shift some subtree at the same time. */
594 const int size = interval_tree_max_height (tree) + 1; 598 if (tree->root != ITREE_NULL)
595 struct interval_stack *stack = interval_stack_create (size);
596 interval_stack_push (stack, tree->root);
597 nodeptr_and_flag nav;
598 while ((nav = interval_stack_pop (stack),
599 node = nav_nodeptr (nav)))
600 { 599 {
601 /* Process in pre-order. */ 600 const int size = interval_tree_max_height (tree) + 1;
602 interval_tree_inherit_offset (tree, node); 601 struct interval_stack *stack = interval_stack_create (size);
603 if (node->right != ITREE_NULL) 602 interval_stack_push (stack, tree->root);
603 nodeptr_and_flag nav;
604 while ((nav = interval_stack_pop (stack),
605 node = nav_nodeptr (nav)))
604 { 606 {
605 if (node->begin > pos) 607 /* Process in pre-order. */
608 interval_tree_inherit_offset (tree->otick, node);
609 if (node->right != ITREE_NULL)
606 { 610 {
607 /* All nodes in this subtree are shifted by length. */ 611 if (node->begin > pos)
608 node->right->offset += length; 612 {
609 ++tree->otick; 613 /* All nodes in this subtree are shifted by length. */
614 node->right->offset += length;
615 ++tree->otick;
616 }
617 else
618 interval_stack_push (stack, node->right);
610 } 619 }
611 else 620 if (node->left != ITREE_NULL
612 interval_stack_push (stack, node->right); 621 && pos <= node->left->limit + node->left->offset)
613 } 622 interval_stack_push (stack, node->left);
614 if (node->left != ITREE_NULL
615 && pos <= node->left->limit + node->left->offset)
616 interval_stack_push (stack, node->left);
617 623
618 /* node->begin == pos implies no front-advance. */ 624 /* node->begin == pos implies no front-advance. */
619 if (node->begin > pos) 625 if (node->begin > pos)
620 node->begin += length; 626 node->begin += length;
621 if (node->end > pos || (node->end == pos && node->rear_advance)) 627 if (node->end > pos || (node->end == pos && node->rear_advance))
622 { 628 {
623 node->end += length; 629 node->end += length;
624 interval_tree_propagate_limit (tree, node); 630 interval_tree_propagate_limit (tree, node);
631 }
625 } 632 }
633 interval_stack_destroy (stack);
626 } 634 }
627 interval_stack_destroy (stack);
628 635
629 /* Reinsert nodes starting at POS having front-advance. */ 636 /* Reinsert nodes starting at POS having front-advance. */
637 nodeptr_and_flag nav;
630 while ((nav = interval_stack_pop (saved), 638 while ((nav = interval_stack_pop (saved),
631 node = nav_nodeptr (nav))) 639 node = nav_nodeptr (nav)))
632 { 640 {
@@ -645,7 +653,7 @@ interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t l
645void 653void
646interval_tree_delete_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length) 654interval_tree_delete_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length)
647{ 655{
648 if (length <= 0 || tree->size == 0) 656 if (length <= 0 || tree->root == ITREE_NULL)
649 return; 657 return;
650 658
651 /* FIXME: Don't allocate stack anew every time. */ 659 /* FIXME: Don't allocate stack anew every time. */
@@ -662,7 +670,7 @@ interval_tree_delete_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t l
662 while ((nav = interval_stack_pop (stack))) 670 while ((nav = interval_stack_pop (stack)))
663 { 671 {
664 node = nav_nodeptr (nav); 672 node = nav_nodeptr (nav);
665 interval_tree_inherit_offset (tree, node); 673 interval_tree_inherit_offset (tree->otick, node);
666 if (node->right != ITREE_NULL) 674 if (node->right != ITREE_NULL)
667 { 675 {
668 if (node->begin > pos + length) 676 if (node->begin > pos + length)
@@ -705,38 +713,14 @@ interval_generator_create (struct interval_tree *tree)
705 const int size = interval_tree_max_height (tree) + 1; 713 const int size = interval_tree_max_height (tree) + 1;
706 714
707 g->stack = interval_stack_create (size); 715 g->stack = interval_stack_create (size);
708 g->tree = tree;
709 g->running = false; 716 g->running = false;
710 interval_generator_reset (g, 1, 0, ITREE_ASCENDING); 717 g->begin = 0;
718 g->end = 0;
719 g->file = NULL;
720 g->line = 0;
711 return g; 721 return g;
712} 722}
713 723
714/* Reset generator G such that it iterates over intervals intersecting
715 with [BEGIN, END) in the given ORDER. */
716
717void
718interval_generator_reset (struct interval_generator *g,
719 ptrdiff_t begin, ptrdiff_t end,
720 enum interval_tree_order order)
721{
722 if (! g) return;
723
724 g->begin = begin;
725 g->end = end;
726 g->order = order;
727 interval_stack_clear (g->stack);
728 if (begin <= end && g->tree->size > 0)
729 interval_stack_push_flagged (g->stack, g->tree->root, false);
730}
731
732/* Allocate enough space for the tree of G in its current shape. */
733
734static inline void
735interval_generator_ensure_space (struct interval_generator *g)
736{
737 interval_stack_ensure_space (g->stack, interval_tree_max_height (g->tree) + 1);
738}
739
740/* Return true, if NODE's interval intersects with [BEGIN, END). 724/* Return true, if NODE's interval intersects with [BEGIN, END).
741 Note: We always include empty nodes at BEGIN (and not at END), 725 Note: We always include empty nodes at BEGIN (and not at END),
742 but if BEGIN==END, then we don't include non-empty nodes starting 726 but if BEGIN==END, then we don't include non-empty nodes starting
@@ -785,7 +769,7 @@ interval_generator_next (struct interval_generator *g)
785 struct interval_node * const left = node->left; 769 struct interval_node * const left = node->left;
786 struct interval_node * const right = node->right; 770 struct interval_node * const right = node->right;
787 771
788 interval_tree_inherit_offset (g->tree, node); 772 interval_tree_inherit_offset (g->otick, node);
789 switch (g->order) 773 switch (g->order)
790 { 774 {
791 case ITREE_ASCENDING: 775 case ITREE_ASCENDING:
@@ -872,11 +856,9 @@ interval_tree_update_limit (const struct interval_tree *tree,
872*/ 856*/
873 857
874static void 858static void
875interval_tree_inherit_offset (const struct interval_tree *tree, 859interval_tree_inherit_offset (uintmax_t otick, struct interval_node *node)
876 struct interval_node *node)
877{ 860{
878 861 if (node->otick == otick)
879 if (node->otick == tree->otick)
880 return; 862 return;
881 863
882 node->begin += node->offset; 864 node->begin += node->offset;
@@ -889,8 +871,8 @@ interval_tree_inherit_offset (const struct interval_tree *tree,
889 node->offset = 0; 871 node->offset = 0;
890 /* FIXME: I wonder when/why this condition can be false, and more generally 872 /* FIXME: I wonder when/why this condition can be false, and more generally
891 why we'd want to propagate offsets that may not be fully up-to-date. */ 873 why we'd want to propagate offsets that may not be fully up-to-date. */
892 if (node == tree->root || node->parent->otick == tree->otick) 874 if (node->parent == ITREE_NULL || node->parent->otick == otick)
893 node->otick = tree->otick; 875 node->otick = otick;
894} 876}
895 877
896/* Update limit of NODE and its ancestors. Stop when it becomes 878/* Update limit of NODE and its ancestors. Stop when it becomes
@@ -910,8 +892,9 @@ interval_tree_propagate_limit (const struct interval_tree *tree,
910 return; 892 return;
911 893
912 while (1) { 894 while (1) {
913 ptrdiff_t newlimit = max (node->end, max (node->left->limit + node->left->offset, 895 ptrdiff_t newlimit = max (node->end,
914 node->right->limit + node->right->offset)); 896 max (node->left->limit + node->left->offset,
897 node->right->limit + node->right->offset));
915 if (newlimit == node->limit) 898 if (newlimit == node->limit)
916 break; 899 break;
917 node->limit = newlimit; 900 node->limit = newlimit;
@@ -930,8 +913,8 @@ interval_tree_rotate_left (struct interval_tree *tree, struct interval_node *nod
930 913
931 struct interval_node *right = node->right; 914 struct interval_node *right = node->right;
932 915
933 interval_tree_inherit_offset (tree, node); 916 interval_tree_inherit_offset (tree->otick, node);
934 interval_tree_inherit_offset (tree, right); 917 interval_tree_inherit_offset (tree->otick, right);
935 918
936 /* Turn right's left subtree into node's right subtree. */ 919 /* Turn right's left subtree into node's right subtree. */
937 node->right = right->left; 920 node->right = right->left;
@@ -972,8 +955,8 @@ interval_tree_rotate_right (struct interval_tree *tree, struct interval_node *no
972 955
973 struct interval_node *left = node->left; 956 struct interval_node *left = node->left;
974 957
975 interval_tree_inherit_offset (tree, node); 958 interval_tree_inherit_offset (tree->otick, node);
976 interval_tree_inherit_offset (tree, left); 959 interval_tree_inherit_offset (tree->otick, left);
977 960
978 node->left = left->right; 961 node->left = left->right;
979 if (left->right != ITREE_NULL) 962 if (left->right != ITREE_NULL)