diff options
| author | Stefan Monnier | 2022-10-09 00:56:24 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2022-10-09 00:56:24 -0400 |
| commit | 4f3f7aebc957732f4fbe5c799da5367f46607680 (patch) | |
| tree | 34e0a0a63b6a6d18f8732a5644e94cfc41616057 /src | |
| parent | fe14454101cfd9951b76549773645b2ffeed66bd (diff) | |
| download | emacs-4f3f7aebc957732f4fbe5c799da5367f46607680.tar.gz emacs-4f3f7aebc957732f4fbe5c799da5367f46607680.zip | |
itree.c: Use `interval_tree_inherit_offset`
The insertion code tried to manipulate the offset in its own way,
and apparently there was a bug in it. Replace that with a call to
`interval_tree_inherit_offset`, making the whole logic a bit simpler,
and fixing a bug along the way (not sure where the bug was, to be honest).
* src/itree.c (interval_tree_insert): Use `interval_tree_inherit_offset`.
Check the tree before insert_fix.
(recurse_check_tree): Don't check RB invariants.
(itree_limits_are_stable): Delete function (subsumed by `check_tree`).
Diffstat (limited to 'src')
| -rw-r--r-- | src/itree.c | 32 |
1 files changed, 11 insertions, 21 deletions
diff --git a/src/itree.c b/src/itree.c index 4ad47b2e3fa..b57c3cc656f 100644 --- a/src/itree.c +++ b/src/itree.c | |||
| @@ -220,9 +220,12 @@ recurse_check_tree (struct interval_node *node, uintmax_t tree_otick, | |||
| 220 | eassert (node->left == ITREE_NULL || node->left->parent == node); | 220 | eassert (node->left == ITREE_NULL || node->left->parent == node); |
| 221 | eassert (node->right == ITREE_NULL || node->right->parent == node); | 221 | eassert (node->right == ITREE_NULL || node->right->parent == node); |
| 222 | 222 | ||
| 223 | /* We don't check the RB invariants here (neither the absence of | ||
| 224 | red+red nor the equal-black-depth), so that we can use this check | ||
| 225 | even while the tree is temporarily breaking some of those invarints. */ | ||
| 223 | /* Red nodes cannot have red parents. */ | 226 | /* Red nodes cannot have red parents. */ |
| 224 | eassert (node->parent == ITREE_NULL | 227 | /* eassert (node->parent == ITREE_NULL |
| 225 | || !(node->red && node->parent->red)); | 228 | || !(node->red && node->parent->red)); */ |
| 226 | 229 | ||
| 227 | eassert (node->offset == 0 || node->otick < tree_otick); | 230 | eassert (node->offset == 0 || node->otick < tree_otick); |
| 228 | 231 | ||
| @@ -493,15 +496,16 @@ interval_tree_insert (struct interval_tree *tree, struct interval_node *node) | |||
| 493 | 496 | ||
| 494 | struct interval_node *parent = ITREE_NULL; | 497 | struct interval_node *parent = ITREE_NULL; |
| 495 | struct interval_node *child = tree->root; | 498 | struct interval_node *child = tree->root; |
| 496 | ptrdiff_t offset = 0; | 499 | uintmax_t otick = tree->otick; |
| 497 | 500 | ||
| 498 | /* Find the insertion point, accumulate node's offset and update | 501 | /* Find the insertion point, accumulate node's offset and update |
| 499 | ancestors limit values. */ | 502 | ancestors limit values. */ |
| 500 | while (child != ITREE_NULL) | 503 | while (child != ITREE_NULL) |
| 501 | { | 504 | { |
| 505 | interval_tree_inherit_offset (otick, child); | ||
| 502 | parent = child; | 506 | parent = child; |
| 503 | offset += child->offset; | 507 | eassert (child->offset == 0); |
| 504 | child->limit = max (child->limit, node->end - offset); | 508 | child->limit = max (child->limit, node->end); |
| 505 | /* This suggests that nodes in the right subtree are strictly | 509 | /* This suggests that nodes in the right subtree are strictly |
| 506 | greater. But this is not true due to later rotations. */ | 510 | greater. But this is not true due to later rotations. */ |
| 507 | child = node->begin <= child->begin ? child->left : child->right; | 511 | child = node->begin <= child->begin ? child->left : child->right; |
| @@ -521,15 +525,13 @@ interval_tree_insert (struct interval_tree *tree, struct interval_node *node) | |||
| 521 | node->right = ITREE_NULL; | 525 | node->right = ITREE_NULL; |
| 522 | node->red = true; | 526 | node->red = true; |
| 523 | node->offset = 0; | 527 | node->offset = 0; |
| 524 | node->begin -= offset; | ||
| 525 | node->end -= offset; | ||
| 526 | node->limit = node->end; | 528 | node->limit = node->end; |
| 527 | node->otick = tree->otick - 1; | 529 | node->otick = otick; |
| 528 | 530 | ||
| 529 | /* Fix/update the tree */ | 531 | /* Fix/update the tree */ |
| 530 | ++tree->size; | 532 | ++tree->size; |
| 531 | interval_tree_insert_fix (tree, node); | ||
| 532 | eassert (check_tree (tree)); | 533 | eassert (check_tree (tree)); |
| 534 | interval_tree_insert_fix (tree, node); | ||
| 533 | } | 535 | } |
| 534 | 536 | ||
| 535 | /* Return true, if NODE is a member of TREE. */ | 537 | /* Return true, if NODE is a member of TREE. */ |
| @@ -567,16 +569,6 @@ itree_limit_is_stable (struct interval_node *node) | |||
| 567 | return (newlimit == node->limit); | 569 | return (newlimit == node->limit); |
| 568 | } | 570 | } |
| 569 | 571 | ||
| 570 | static inline bool | ||
| 571 | itree_limits_are_stable (struct interval_node *node) | ||
| 572 | { | ||
| 573 | if (node == ITREE_NULL) | ||
| 574 | return true; | ||
| 575 | return itree_limit_is_stable (node) | ||
| 576 | && itree_limits_are_stable (node->right) | ||
| 577 | && itree_limits_are_stable (node->left); | ||
| 578 | } | ||
| 579 | |||
| 580 | static struct interval_node* | 572 | static struct interval_node* |
| 581 | interval_tree_subtree_min (uintmax_t otick, struct interval_node *node) | 573 | interval_tree_subtree_min (uintmax_t otick, struct interval_node *node) |
| 582 | { | 574 | { |
| @@ -692,7 +684,6 @@ interval_tree_remove_fix (struct interval_tree *tree, | |||
| 692 | struct interval_node* | 684 | struct interval_node* |
| 693 | interval_tree_remove (struct interval_tree *tree, struct interval_node *node) | 685 | interval_tree_remove (struct interval_tree *tree, struct interval_node *node) |
| 694 | { | 686 | { |
| 695 | /* eassert (itree_limits_are_stable (tree->root)); */ | ||
| 696 | eassert (interval_tree_contains (tree, node)); | 687 | eassert (interval_tree_contains (tree, node)); |
| 697 | eassert (check_tree (tree)); | 688 | eassert (check_tree (tree)); |
| 698 | 689 | ||
| @@ -770,7 +761,6 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node) | |||
| 770 | --tree->size; | 761 | --tree->size; |
| 771 | 762 | ||
| 772 | eassert ((tree->size == 0) == (tree->root == ITREE_NULL)); | 763 | eassert ((tree->size == 0) == (tree->root == ITREE_NULL)); |
| 773 | /* eassert (itree_limits_are_stable (tree->root)); */ | ||
| 774 | eassert (check_tree (tree)); | 764 | eassert (check_tree (tree)); |
| 775 | 765 | ||
| 776 | return node; | 766 | return node; |