null->begin = PTRDIFF_MIN;
null->end = PTRDIFF_MIN;
null->limit = PTRDIFF_MIN; /* => max(x, null.limit) = x */
- null->color = ITREE_BLACK;
+ null->red = false;
tree->root = null;
tree->otick = 1;
tree->size = 0;
- tree->iter_running = 0;
+ tree->iter_running = false;
}
#ifdef ITREE_TESTING
node->parent = parent;
node->left = &tree->null;
node->right = &tree->null;
- node->color = ITREE_RED;
+ node->red = true;
node->offset = 0;
node->begin -= offset;
node->end -= offset;
{
struct interval_node *subst =
(node->right == &tree->null) ? node->left : node->right;
- if (node->color == ITREE_BLACK)
+ if (!node->red)
broken = subst;
interval_tree_transplant (tree, subst, node);
interval_tree_propagate_limit (tree, subst);
struct interval_node *min = interval_tree_subtree_min (tree, node->right);
struct interval_node *min_right = min->right;
- if (min->color == ITREE_BLACK)
+ if (!min->red)
broken = min->right;
if (min->parent == node)
min_right->parent = min; /* set parent, if min_right = null */
interval_tree_transplant (tree, min, node);
min->left = node->left;
min->left->parent = min;
- min->color = node->color;
+ min->red = node->red;
interval_tree_propagate_limit (tree, min_right);
interval_tree_propagate_limit (tree, min);
}
if (tree->iter_running)
emacs_abort ();
interval_generator_reset (tree->iter, begin, end, order);
- tree->iter_running = 1;
+ tree->iter_running = true;
tree->file = file;
tree->line = line;
}
{
if (! tree->iter_running)
emacs_abort ();
- tree->iter_running = 0;
+ tree->iter_running = false;
}
/* Return the next node of the iterator in the order given when it was
g->stack = interval_stack_create (size);
g->tree = tree;
- interval_generator_reset (g, 1, 0, 0);
+ interval_generator_reset (g, 1, 0, ITREE_ASCENDING);
return g;
}
interval_stack_ensure_space (g->stack, interval_tree_max_height (g->tree) + 1);
}
-/* Return true, if NODE's interval intersects with [BEGIN, END). */
+/* Return true, if NODE's interval intersects with [BEGIN, END).
+ Note: We always include empty nodes at BEGIN (and not at END),
+ but if BEGIN==END, then we don't include non-empty nodes starting
+ at BEGIN or ending at END. This seems to match the behavior of the
+ old overlays code but it's not clear if it's The Right Thing
+ (e.g. it breaks the expectation that if NODE1 is included, then
+ a NODE2 strictly bigger than NODE1 should also be included). */
static inline bool
interval_node_intersects (const struct interval_node *node,
struct interval_node * const null = &g->tree->null;
struct interval_node *node;
- do {
- node = interval_stack_pop (g->stack);
+ /* The `visited` flag stored in each node is used here (and only here):
+ We keep a "workstack" of nodes we need to consider. This stack
+ consist of nodes of two types: nodes that we have decided
+ should be returned by the generator, and nodes which we may
+ need to consider (including checking their children).
+ We start an iteration with a stack containing just the root
+ node marked as "not visited" which means that it (and its children)
+ needs to be considered but we haven't yet decided whether it's included
+ in the generator's output. */
+
+ /* FIXME: We should move the `visited` flag to the stack: each entry
+ there should simply consist of a node and a bool (the `visited` status)
+ so this internal implementation detail doesn't leak into the
+ `interval_node` structure.
+ [ In theory it would also allow multiple iterations to be active
+ at the same time, tho that does not seem particularly useful at
+ this time and would require further changes anyway. ]
+ To save space on the stack, we could hijack the LSB bit of the `node*`
+ word to hold the `visited` bit. */
- while (node && ! node->visited)
+ do {
+ while ((node = interval_stack_pop (g->stack))
+ && ! node->visited)
{
struct interval_node * const left = node->left;
struct interval_node * const right = node->right;
interval_stack_push_flagged (g->stack, node, true);
break;
}
- node = interval_stack_pop (g->stack);
}
/* Node may have been invalidated by interval_generator_narrow
after it was pushed: Check if it still intersects. */
interval_generator_narrow (struct interval_generator *g,
ptrdiff_t begin, ptrdiff_t end)
{
+ eassert (begin >= g->begin);
+ eassert (end <= g->end);
g->begin = max (begin, g->begin);
g->end = min (end, g->end);
}
static void
interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node)
{
- while (node->parent->color == ITREE_RED)
+ while (node->parent->red)
{
/* NODE is red and its parent is red. This is a violation of
red-black tree property #3. */
our "uncle". */
struct interval_node *uncle = node->parent->parent->right;
- if (uncle->color == ITREE_RED) /* case 1.a */
+ if (uncle->red) /* case 1.a */
{
/* Uncle and parent are red but should be black because
NODE is red. Change the colors accordingly and
proceed with the grandparent. */
- node->parent->color = ITREE_BLACK;
- uncle->color = ITREE_BLACK;
- node->parent->parent->color = ITREE_RED;
+ node->parent->red = false;
+ uncle->red = false;
+ node->parent->parent->red = true;
node = node->parent->parent;
}
else
interval_tree_rotate_left (tree, node);
}
/* case 3.a */
- node->parent->color = ITREE_BLACK;
- node->parent->parent->color = ITREE_RED;
+ node->parent->red = false;
+ node->parent->parent->red = true;
interval_tree_rotate_right (tree, node->parent->parent);
}
}
/* This is the symmetrical case of above. */
struct interval_node *uncle = node->parent->parent->left;
- if (uncle->color == ITREE_RED) /* case 1.b */
+ if (uncle->red) /* case 1.b */
{
- node->parent->color = ITREE_BLACK;
- uncle->color = ITREE_BLACK;
- node->parent->parent->color = ITREE_RED;
+ node->parent->red = false;
+ uncle->red = false;
+ node->parent->parent->red = true;
node = node->parent->parent;
}
else
interval_tree_rotate_right (tree, node);
}
/* case 3.b */
- node->parent->color = ITREE_BLACK;
- node->parent->parent->color = ITREE_RED;
+ node->parent->red = false;
+ node->parent->parent->red = true;
interval_tree_rotate_left (tree, node->parent->parent);
}
}
/* The root may have been changed to red due to the algorithm. Set
it to black so that property #5 is satisfied. */
- tree->root->color = ITREE_BLACK;
+ tree->root->red = false;
}
/* Repair the tree after a deletion. Part of the RB-Tree
static void
interval_tree_remove_fix (struct interval_tree *tree, struct interval_node *node)
{
- while (node != tree->root && node->color == ITREE_BLACK)
+ while (node != tree->root && !node->red)
{
if (node == node->parent->left)
{
struct interval_node *other = node->parent->right;
- if (other->color == ITREE_RED) /* case 1.a */
+ if (other->red) /* case 1.a */
{
- other->color = ITREE_BLACK;
- node->parent->color = ITREE_RED;
+ other->red = false;
+ node->parent->red = true;
interval_tree_rotate_left (tree, node->parent);
other = node->parent->right;
}
- if (other->left->color == ITREE_BLACK /* 2.a */
- && other->right->color == ITREE_BLACK)
+ if (!other->left->red /* 2.a */
+ && !other->right->red)
{
- other->color = ITREE_RED;
+ other->red = true;
node = node->parent;
}
else
{
- if (other->right->color == ITREE_BLACK) /* 3.a */
+ if (!other->right->red) /* 3.a */
{
- other->left->color = ITREE_BLACK;
- other->color = ITREE_RED;
+ other->left->red = false;
+ other->red = true;
interval_tree_rotate_right (tree, other);
other = node->parent->right;
}
- other->color = node->parent->color; /* 4.a */
- node->parent->color = ITREE_BLACK;
- other->right->color = ITREE_BLACK;
+ other->red = node->parent->red; /* 4.a */
+ node->parent->red = false;
+ other->right->red = false;
interval_tree_rotate_left (tree, node->parent);
node = tree->root;
}
{
struct interval_node *other = node->parent->left;
- if (other->color == ITREE_RED) /* 1.b */
+ if (other->red) /* 1.b */
{
- other->color = ITREE_BLACK;
- node->parent->color = ITREE_RED;
+ other->red = false;
+ node->parent->red = true;
interval_tree_rotate_right (tree, node->parent);
other = node->parent->left;
}
- if (other->right->color == ITREE_BLACK /* 2.b */
- && other->left->color == ITREE_BLACK)
+ if (!other->right->red /* 2.b */
+ && !other->left->red)
{
- other->color = ITREE_RED;
+ other->red = true;
node = node->parent;
}
else
{
- if (other->left->color == ITREE_BLACK) /* 3.b */
+ if (!other->left->red) /* 3.b */
{
- other->right->color = ITREE_BLACK;
- other->color = ITREE_RED;
+ other->right->red = false;
+ other->red = true;
interval_tree_rotate_left (tree, other);
other = node->parent->left;
}
- other->color = node->parent->color; /* 4.b */
- node->parent->color = ITREE_BLACK;
- other->left->color = ITREE_BLACK;
+ other->red = node->parent->red; /* 4.b */
+ node->parent->red = false;
+ other->left->red = false;
interval_tree_rotate_right (tree, node->parent);
node = tree->root;
}
}
}
- node->color = ITREE_BLACK;
+ node->red = false;
}
/* Link node SOURCE in DEST's place. */