| | <@xref{\NODE\, , Find parent of a TBST node; tbst =>.> trb,327}
void ** trb_probe (struct trb_table *tree, void *item) {
struct trb_node *p; /* Traverses tree looking for insertion point. */
struct trb_node *n; /* Newly inserted node. */
int dir; /* Side of p on which n is inserted. */
assert (tree != NULL && item != NULL);
<@xref{\NODE\, , Step 1: Search TBST for insertion point; tbst =>.> trb,255}
<@xref{\NODE\, , Step 2: Insert TRB node.>,339}
p = n;
for (;;) {
struct trb_node *f, *g;
f = find_parent (tree, p);
if (f == (struct trb_node *) &tree->trb_root || f->trb_color == TRB_BLACK)
break;
g = find_parent (tree, f);
if (g == (struct trb_node *) &tree->trb_root)
break;
if (g->trb_link[0] == f) {
struct trb_node *y = g->trb_link[1];
if (g->trb_tag[1] == TRB_CHILD && y->trb_color == TRB_RED) {
f->trb_color = y->trb_color = TRB_BLACK;
g->trb_color = TRB_RED;
p = g;
} else {
struct trb_node *c, *x;
if (f->trb_link[0] == p)
y = f;
else {
x = f;
y = x->trb_link[1];
x->trb_link[1] = y->trb_link[0];
y->trb_link[0] = x;
g->trb_link[0] = y;
if (y->trb_tag[0] == TRB_THREAD) {
y->trb_tag[0] = TRB_CHILD;
x->trb_tag[1] = TRB_THREAD;
x->trb_link[1] = y;
}
}
c = find_parent (tree, g);
c->trb_link[c->trb_link[0] != g] = y;
x = g;
x->trb_color = TRB_RED;
y->trb_color = TRB_BLACK;
x->trb_link[0] = y->trb_link[1];
y->trb_link[1] = x;
if (y->trb_tag[1] == TRB_THREAD) {
y->trb_tag[1] = TRB_CHILD;
x->trb_tag[0] = TRB_THREAD;
x->trb_link[0] = y;
}
break;
}
} else {
struct trb_node *y = g->trb_link[0];
if (g->trb_tag[0] == TRB_CHILD && y->trb_color == TRB_RED) {
f->trb_color = y->trb_color = TRB_BLACK;
g->trb_color = TRB_RED;
p = g;
} else {
struct trb_node *c, *x;
if (f->trb_link[1] == p)
y = f;
else {
x = f;
y = x->trb_link[0];
x->trb_link[0] = y->trb_link[1];
y->trb_link[1] = x;
g->trb_link[1] = y;
if (y->trb_tag[1] == TRB_THREAD) {
y->trb_tag[1] = TRB_CHILD;
x->trb_tag[0] = TRB_THREAD;
x->trb_link[0] = y;
}
}
c = find_parent (tree, g);
c->trb_link[c->trb_link[0] != g] = y;
x = g;
x->trb_color = TRB_RED;
y->trb_color = TRB_BLACK;
x->trb_link[1] = y->trb_link[0];
y->trb_link[0] = x;
if (y->trb_tag[0] == TRB_THREAD) {
y->trb_tag[0] = TRB_CHILD;
x->trb_tag[1] = TRB_THREAD;
x->trb_link[1] = y;
}
break;
}
}
}
tree->trb_root->trb_color = TRB_BLACK;
return &n->trb_data;
}
|