示例#1
0
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;
}
示例#2
0
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;
    }
}
示例#3
0
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;
}