/* 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 ** rtbst_probe (struct rtbst_table *tree, void *item) { struct rtbst_node *p; /* Current node in search. */ int dir; /* Side of |p| on which to insert the new node. */ struct rtbst_node *n; /* New node. */ if (tree->rtbst_root != NULL) for (p = tree->rtbst_root; ; p = p->rtbst_link[dir]) { int cmp = tree->rtbst_compare (item, p->rtbst_data, tree->rtbst_param); if (cmp == 0) return &p->rtbst_data; dir = cmp > 0; if (dir == 0) { if (p->rtbst_link[0] == NULL) break; } else /* |dir == 1| */ { if (p->rtbst_rtag == RTBST_THREAD) break; } } else { p = (struct rtbst_node *) &tree->rtbst_root; dir = 0; } n = tree->rtbst_alloc->libavl_malloc (tree->rtbst_alloc, sizeof *n); if (n == NULL) return NULL; tree->rtbst_count++; n->rtbst_data = item; n->rtbst_link[0] = NULL; if (dir == 0) { if (tree->rtbst_root != NULL) n->rtbst_link[1] = p; else n->rtbst_link[1] = NULL; } else /* |dir == 1| */ { p->rtbst_rtag = RTBST_CHILD; n->rtbst_link[1] = p->rtbst_link[1]; } n->rtbst_rtag = RTBST_THREAD; p->rtbst_link[dir] = n; return &n->rtbst_data; }