diff options
| author | Stefan Monnier | 2022-10-02 11:11:57 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2022-10-02 11:11:57 -0400 |
| commit | ba5fe8e7895a2cbfd2d666ca88c0ed96a73fbe29 (patch) | |
| tree | 86ef32619bf43d7636281a565d6168a3025ee60f /src | |
| parent | c3eb6c0563cc95b2134af9fe0ee6f304ddbb0480 (diff) | |
| download | emacs-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.c | 151 |
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 | ||
| 100 | static struct interval_node *interval_tree_validate (struct interval_tree *, struct interval_node *); | 100 | static struct interval_node *interval_tree_validate (struct interval_tree *, struct interval_node *); |
| 101 | static void interval_generator_ensure_space (struct interval_generator *); | ||
| 102 | static bool interval_node_intersects (const struct interval_node *, ptrdiff_t, ptrdiff_t); | 101 | static bool interval_node_intersects (const struct interval_node *, ptrdiff_t, ptrdiff_t); |
| 103 | static int interval_tree_max_height (const struct interval_tree *); | 102 | static int interval_tree_max_height (const struct interval_tree *); |
| 104 | static void interval_tree_update_limit (const struct interval_tree *, struct interval_node *); | 103 | static void interval_tree_update_limit (const struct interval_tree *, struct interval_node *); |
| 105 | static void interval_tree_inherit_offset (const struct interval_tree *, struct interval_node *); | 104 | static void interval_tree_inherit_offset (uintmax_t otick, struct interval_node *); |
| 106 | static void interval_tree_propagate_limit (const struct interval_tree *, struct interval_node *); | 105 | static void interval_tree_propagate_limit (const struct interval_tree *, struct interval_node *); |
| 107 | static void interval_tree_rotate_left (struct interval_tree *, struct interval_node *); | 106 | static void interval_tree_rotate_left (struct interval_tree *, struct interval_node *); |
| 108 | static void interval_tree_rotate_right (struct interval_tree *, struct interval_node *); | 107 | static 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 | |||
| 112 | static struct interval_node *interval_tree_subtree_min (const struct interval_tree *, struct interval_node *); | 111 | static struct interval_node *interval_tree_subtree_min (const struct interval_tree *, struct interval_node *); |
| 113 | static struct interval_generator* interval_generator_create (struct interval_tree *); | 112 | static struct interval_generator* interval_generator_create (struct interval_tree *); |
| 114 | static void interval_generator_destroy (struct interval_generator *); | 113 | static void interval_generator_destroy (struct interval_generator *); |
| 115 | static void interval_generator_reset (struct interval_generator *, | ||
| 116 | ptrdiff_t, ptrdiff_t, | ||
| 117 | enum interval_tree_order); | ||
| 118 | static inline void interval_tree_iter_ensure_space (struct interval_tree *); | 114 | static 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. */ |
| 143 | struct interval_generator | 139 | struct 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 | |||
| 222 | interval_stack_push_flagged (struct interval_stack *stack, | 218 | interval_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) | |||
| 549 | static inline void | 553 | static inline void |
| 550 | interval_tree_iter_ensure_space (struct interval_tree *tree) | 554 | interval_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 | ||
| 555 | static int | 560 | static int |
| @@ -570,7 +575,7 @@ interval_tree_max_height (const struct interval_tree *tree) | |||
| 570 | void | 575 | void |
| 571 | interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length) | 576 | interval_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 | |||
| 645 | void | 653 | void |
| 646 | interval_tree_delete_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t length) | 654 | interval_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 | |||
| 717 | void | ||
| 718 | interval_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 | |||
| 734 | static inline void | ||
| 735 | interval_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 | ||
| 874 | static void | 858 | static void |
| 875 | interval_tree_inherit_offset (const struct interval_tree *tree, | 859 | interval_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) |