LEAFTYPE radix_del(struct ROOTSTRUCT * tree, LEAFTYPE leaf, EXTRA_ARG aux) { LEAFTYPE result; struct _internal_node * node, * parent; uint32_t dir, dir2; if (tree->leafcount == 0) return NO_LEAF; if (tree->leafcount == 1) { result = tree->root.leaf; if (COMPARE(result, leaf) == -1) { tree->root.leaf = NO_LEAF; tree->leafcount --; return result; } else return NO_LEAF; } /* else */ node = tree->root.node; while (1) { dir = DECIDE(leaf, node->critbit, aux); if (IS_LEAF(node, dir)) { result = node->child[dir].leaf; break; } else { node = node->child[dir].node; } } if (COMPARE(result, leaf) == -1) { parent = tree->root.node; while (1) { dir2 = DECIDE(leaf, parent->critbit, aux); if (parent->child[dir2].node == node) break; else parent = parent->child[dir2].node; } if (IS_LEAF(node, 1 - dir)) { parent->child[dir2].leaf = node->child[1 - dir].leaf; SET_LEAF(parent, dir2); } else { parent->child[dir2].node = node->child[1 - dir].node; } tree->leafcount --; DEALLOC(node); return result; } else return NO_LEAF; }
LEAFTYPE radix_add(struct ROOTSTRUCT * tree, LEAFTYPE leaf, EXTRA_ARG aux, int should_replace, int* error) { LEAFTYPE result; struct _internal_node * node, * parent, * child; uint32_t dir, dir2; int32_t critbit; *error = 0; if (tree->leafcount == 0) { tree->root.leaf = leaf; tree->leafcount ++; return NO_LEAF; } else if (tree->leafcount == 1) { result = tree->root.leaf; critbit = COMPARE(leaf, result); if (critbit == -1) { if (should_replace) { node->child[dir].leaf = leaf; return result; } else return leaf; } else { node = (struct _internal_node *) ALLOC(sizeof (struct _internal_node)); if (node == NULL) { *error = -1; return NO_LEAF; } else { node->critbit = critbit; dir = DECIDE(leaf, critbit, aux); node->child[dir].leaf = leaf; SET_LEAF(node, dir); } result = tree->root.leaf; node->child[1 - dir].leaf = tree->root.leaf; SET_LEAF(node, 1 - dir); tree->root.node = node; tree->leafcount ++; return NO_LEAF; } } /* else */ node = tree->root.node; while (1) { dir = DECIDE(leaf, node->critbit, aux); if (IS_LEAF(node, dir)) { result = node->child[dir].leaf; break; } else { node = node->child[dir].node; } } critbit = COMPARE(leaf, result); if (critbit == -1) { if (should_replace) { node->child[dir].leaf = leaf; return result; } else return leaf; } else { node = (struct _internal_node *) ALLOC(sizeof (struct _internal_node)); if (node == NULL) { *error = -1; return NO_LEAF; } else { node->critbit = critbit; dir = DECIDE(leaf, critbit, aux); node->child[dir].leaf = leaf; SET_LEAF(node, dir); } child = tree->root.node; if (node->critbit < child->critbit) { node->child[1 - dir].node = child; SET_NODE(node, 1 - dir); tree->root.node = node; } else while (1) { parent = child; dir2 = DECIDE(leaf, parent->critbit, aux); if (IS_LEAF(parent, dir2)) { result = parent->child[dir2].leaf; //node->child[1 - dir].leaf = tree->root.leaf; node->child[1 - dir].leaf = parent->child[dir2].leaf; SET_LEAF(node, 1 - dir); parent->child[dir2].node = node; SET_NODE(parent, dir2); break; } else { child = parent->child[dir2].node; if (node->critbit < child->critbit) { node->child[1 - dir].node = child; SET_NODE(node, 1 - dir); parent->child[dir2].node = node; SET_NODE(parent, dir2); break; } } } tree->leafcount ++; return NO_LEAF; } }
static void* recursive_insert(art_node *n, art_node **ref, const unsigned char *key, int key_len, void *value, int depth, int *old) { // If we are at a NULL node, inject a leaf if (!n) { *ref = (art_node*)SET_LEAF(make_leaf(key, key_len, value)); return NULL; } // If we are at a leaf, we need to replace it with a node if (IS_LEAF(n)) { art_leaf *l = LEAF_RAW(n); // Check if we are updating an existing value if (!leaf_matches(l, key, key_len, depth)) { *old = 1; void *old_val = l->value; l->value = value; return old_val; } // New value, we must split the leaf into a node4 art_node4 *new_node = (art_node4*)alloc_node(NODE4); // Create a new leaf art_leaf *l2 = make_leaf(key, key_len, value); // Determine longest prefix int longest_prefix = longest_common_prefix(l, l2, depth); new_node->n.partial_len = longest_prefix; memcpy(new_node->n.partial, key+depth, min(MAX_PREFIX_LEN, longest_prefix)); // Add the leafs to the new node4 *ref = (art_node*)new_node; add_child4(new_node, ref, l->key[depth+longest_prefix], SET_LEAF(l)); add_child4(new_node, ref, l2->key[depth+longest_prefix], SET_LEAF(l2)); return NULL; } // Check if given node has a prefix if (n->partial_len) { // Determine if the prefixes differ, since we need to split int prefix_diff = prefix_mismatch(n, key, key_len, depth); if ((uint32_t)prefix_diff >= n->partial_len) { depth += n->partial_len; goto RECURSE_SEARCH; } // Create a new node art_node4 *new_node = (art_node4*)alloc_node(NODE4); *ref = (art_node*)new_node; new_node->n.partial_len = prefix_diff; memcpy(new_node->n.partial, n->partial, min(MAX_PREFIX_LEN, prefix_diff)); // Adjust the prefix of the old node if (n->partial_len <= MAX_PREFIX_LEN) { add_child4(new_node, ref, n->partial[prefix_diff], n); n->partial_len -= (prefix_diff+1); memmove(n->partial, n->partial+prefix_diff+1, min(MAX_PREFIX_LEN, n->partial_len)); } else { n->partial_len -= (prefix_diff+1); art_leaf *l = minimum(n); add_child4(new_node, ref, l->key[depth+prefix_diff], n); memcpy(n->partial, l->key+depth+prefix_diff+1, min(MAX_PREFIX_LEN, n->partial_len)); } // Insert the new leaf art_leaf *l = make_leaf(key, key_len, value); add_child4(new_node, ref, key[depth+prefix_diff], SET_LEAF(l)); return NULL; } RECURSE_SEARCH:; // Find a child to recurse to art_node **child = find_child(n, key[depth]); if (child) { return recursive_insert(*child, child, key, key_len, value, depth+1, old); } // No child, node goes within us art_leaf *l = make_leaf(key, key_len, value); add_child(n, ref, key[depth], SET_LEAF(l)); return NULL; }