/* Inserts |item| into |tree| and returns a pointer to |item|'s address. If a duplicate item is found in the tree, returns a pointer to the duplicate without inserting |item|. Returns |NULL| in case of memory allocation failure. */ void ** rb_probe (struct rb_table *tree, void *item) { struct rb_node *pa[RB_MAX_HEIGHT]; /* Nodes on stack. */ unsigned char da[RB_MAX_HEIGHT]; /* Directions moved from stack nodes. */ int k; /* Stack height. */ struct rb_node *p; /* Traverses tree looking for insertion point. */ struct rb_node *n; /* Newly inserted node. */ assert (tree != NULL && item != NULL); pa[0] = (struct rb_node *) &tree->rb_root; da[0] = 0; k = 1; for (p = tree->rb_root; p != NULL; p = p->rb_link[da[k - 1]]) { int cmp = tree->rb_compare (item, p->rb_data, tree->rb_param); if (cmp == 0) return &p->rb_data; pa[k] = p; da[k++] = cmp > 0; } n = pa[k - 1]->rb_link[da[k - 1]] = tree->rb_alloc->libavl_malloc (tree->rb_alloc, sizeof *n); if (n == NULL) return NULL; n->rb_data = item; n->rb_link[0] = n->rb_link[1] = NULL; n->rb_color = RB_BLACK; tree->rb_count++; tree->rb_generation++; while (k >= 2) { struct rb_node *q = pa[k - 1]->rb_link[da[k - 1]]; if (pa[k - 1]->rb_color == RB_BLACK) { q->rb_color = RB_RED; break; } if (da[k - 2] == 0) { struct rb_node *y = pa[k - 2]->rb_link[1]; if (y != NULL && y->rb_color == RB_RED) { pa[k - 1]->rb_color = y->rb_color = RB_BLACK; q->rb_color = RB_RED; k -= 2; } else { struct rb_node *x; if (da[k - 1] == 0) y = pa[k - 1]; else { x = pa[k - 1]; y = pa[k - 2]->rb_link[0] = q; x->rb_link[1] = y->rb_link[0]; q = y->rb_link[0] = x; } x = pa[k - 2]; x->rb_color = q->rb_color = RB_RED; y->rb_color = RB_BLACK; x->rb_link[0] = y->rb_link[1]; y->rb_link[1] = x; pa[k - 3]->rb_link[da[k - 3]] = y; break; } } else { struct rb_node *y = pa[k - 2]->rb_link[0]; if (y != NULL && y->rb_color == RB_RED) { pa[k - 1]->rb_color = y->rb_color = RB_BLACK; q->rb_color = RB_RED; k -= 2; } else { struct rb_node *x; if (da[k - 1] == 1) y = pa[k - 1]; else { x = pa[k - 1]; y = pa[k - 2]->rb_link[1] = q; x->rb_link[0] = y->rb_link[1]; q = y->rb_link[1] = x; } x = pa[k - 2]; x->rb_color = q->rb_color = RB_RED; y->rb_color = RB_BLACK; x->rb_link[1] = y->rb_link[0]; y->rb_link[0] = x; pa[k - 3]->rb_link[da[k - 3]] = y; break; } } } return &n->rb_data; }