/* * Insert an item to the tree. * Return 0 if a new node was created, 1 if a node was updated, or -1 on error. */ int mtree_trie_insert(struct mtree_trie *trie, const char *key, void *item) { struct mtree_trie_node *u; struct mtree_trie_node *node; size_t bit; assert(trie != NULL); assert(item != NULL); assert(key != NULL && *key != '\0'); u = find_node(trie, key); if (u != NULL && strcmp(u->key, key) == 0) { /* * Already in the trie, just update the item. */ if (trie->free_fn != NULL && u->item != NULL) trie->free_fn(u->item); u->item = item; return (1); } if ((node = create_node(key, item)) == NULL) return (-1); if (u == NULL) { /* * Trie is empty, insert to the left under the head. */ for (bit = 0; KEY_BIT(key, node->key_len, bit) == 0; bit++) ; node->bit = bit; node->left = trie->top; trie->top->left = node; } else { for (bit = 0;; bit++) { int kbit = KEY_BIT(key, node->key_len, bit); if (kbit != KEY_BIT(u->key, u->key_len, bit)) { if (kbit == 0) node->right = NULL; else node->left = NULL; node->bit = bit; break; } } trie->top->left = insert_node(trie->top->left, node, trie->top); } return (0); }
static struct mtree_trie * insert_node(struct mtree_trie *u, struct mtree_trie *node, struct mtree_trie *prev) { if (u->bit >= node->bit || u->bit <= prev->bit) { if (node->left == node) node->right = u; else node->left = u; return (node); } if (KEY_BIT(node->key, node->key_len, u->bit) == 0) u->left = insert_node(u->left, node, u); else u->right = insert_node(u->right, node, u); return (u); }
static struct mtree_trie_node * find_node(struct mtree_trie *trie, const char *key) { struct mtree_trie_node *u; size_t len; size_t d; if (trie->top->left == trie->top) return (NULL); u = trie->top->left; len = strlen(key); do { d = u->bit; u = KEY_BIT(key, len, d) == 0 ? u->left : u->right; } while (u != NULL && u->bit > d); return (u); }