/**
 * Split a range into 3 parts to accommodate a tree-node
 * @param d the dom in question
 * @param n the node in the tree
 * @param r the out of tree range r to split up
 */
static void dom_breakup_range( dom *d, node *n, node *r )
{
    node *r2;
    if ( node_offset(n) > node_offset(r) )
    {
        node_split( r, node_offset(n) );
        r2 = node_next_sibling( r );
        node_detach_sibling( r, NULL );
        dom_store_range( d, node_to_range(r) );
        //queue_push( d->q, node_to_range(r) );
        node_dispose( r );
    }
    else
        r2 = r;
    if ( node_end(r2)>node_end(n) )
    {
        node *r3;
        node_split( r2, node_end(n) );
        r3 = node_next_sibling(r2);
        node_detach_sibling(r3,r2);
        dom_store_range( d, node_to_range(r3) );
        //queue_push( d->q, node_to_range(r3) );
        node_dispose(r3);
    }
    dom_node_equals( d, n, r2 );
}
/**
 * Try to make the new node into a parent of the tree-node n. The problem 
 * here is that we must include any siblings of n in r if they fit.
 * @param n the node above which to add the parent
 * @param r the new unattached node 
 */
static void dom_make_parent( dom *d, node *n, node *r )
{
    node *parent = node_parent(n);
    node *prev = node_prec_sibling( n );
    if ( parent==NULL )
        printf("parent is NULL\n");
    //fprintf( stderr,"n: %s %d:%d; r %s %d:%d\n",node_name(n),node_offset(n),
    //    node_end(n),node_name(r),node_offset(r),node_end(r));
    //node_debug_check_siblings( node_first_child(parent) );
    while ( n != NULL && !node_follows(r,n) )
    {
        node *next = node_next_sibling(n);
        if ( dom_nests(d,node_name(n),node_name(r)) )
        {
            if ( range_encloses_node(n,r) || range_equals_node(n,r) )
            {
                node_detach_sibling( n, prev );
                node_add_child( r, n );
                if ( node_overlaps_on_right(parent,r) )
                {
                    node_split( r, node_end(parent) );
                    node *r2 = node_next_sibling( r );
                    node_detach_sibling( r, NULL );
                    dom_store_range( d, node_to_range(r2) );
                    node_dispose( r2 );
                }
            }
            else if ( node_overlaps_on_left(n,r) )
            {
                node_split( n, node_end(r) );
                node_detach_sibling( n, prev );
                node_add_child( r, n );
                break;
            }
            else
                break;
        }
        else 
        {
            // split off the rest of r and and push it back
            // Q: what happens to r??
            node *r2;
            node_split( r, node_offset(n) );
            r2 = node_next_sibling( r );
            node_detach_sibling( r, NULL );
            dom_store_range( d, node_to_range(r2) );
            //queue_push( d->q, node_to_range(r2) );
            node_dispose( r2 );
            break;
        }
        n = next;
        if ( n != NULL )
            prev = node_prec_sibling( n );
    }
    // make n's original parent the parent of r
    node_add_child( parent, r );
   // node_debug_check_siblings( node_first_child(parent) );
}
/**
 * Split a node into 3 parts to accommodate a range
 * @param d the dom in question
 * @param n the node in the tree to split up
 * @param r the out of tree node r that overlaps with n
 */
static void dom_breakup_node( dom *d, node *n, node *r )
{
    node *n2;
    if ( node_offset(r) > node_offset(n) )
    {
        node_split( n, node_offset(r) );
        n2 = node_next_sibling( n );
    }
    else
        n2 = n;
    if ( node_end(r) < node_end(n2) )
        node_split( n2, node_end(r) );
    dom_node_equals( d, n2, r );
}
Exemple #4
0
static node_t *node_put(tree_t *tree, node_t *p, node_t *child)
{
	if (IS_NIL(p))
		p = child;
	else {
		int d = tree->compare(child->key, p->key);

		if (d == 0)
			return NULL;

		if (d < 0) {
			node_t *q = node_put(tree, p->left, child);

			if (!q)
				return NULL;

			p->left = q;
		} else {
			node_t *q = node_put(tree, p->right, child);

			if (!q)
				return NULL;

			p->right = q;
		}

		p = node_split(node_skew(p));
	}

	return p;
}
Exemple #5
0
static node_t *node_rebalance(node_t *p)
{
	if ((p->left->level < (p->level - 1))
			|| (p->right->level < (p->level - 1))) {
		if (p->right->level > --p->level)
			p->right->level = p->level;

		p = node_skew(p);
		p->right = node_skew(p->right);
		p->right->right = node_skew(p->right->right);
		p = node_split(p);
		p->right = node_split(p->right);
	}

	return p;
}
Exemple #6
0
static value_t *find_below(hattrie_t *T, node_ptr parent, const char *key, size_t len)
{
    /* consume all trie nodes, now parent must be trie and child anything */
    node_ptr node = hattrie_consume(&parent, &key, &len, 0);
    assert(*parent.flag & NODE_TYPE_TRIE);

    /* if the key has been consumed on a trie node, use its value */
    if (len == 0) {
        if (*node.flag & NODE_TYPE_TRIE) {
            return hattrie_useval(T, node);
        } else if (*node.flag & NODE_TYPE_HYBRID_BUCKET) {
            return hattrie_useval(T, parent);
        }
    }

#ifdef HHASH_MAX_FILL
    /* preemptively split the bucket if fill is over threshold */
    if (node.b->weight >= node.b->size * HHASH_MAX_FILL) {
        node_split(T, parent, node);
        return find_below(T, parent, key, len);
    }
#endif

    /* attempt to fit new element and split if it doesn't fit */
    value_t *val = NULL;
    assert(len > 0);
    if (*node.flag & NODE_TYPE_PURE_BUCKET) {
        val = hhash_map(node.b, key + 1, len - 1, HHASH_INSERT);
    }
    else {
        val = hhash_map(node.b, key, len, HHASH_INSERT);
    }

    /* not inserted, recursively split */
    if (val == NULL) {
        node_split(T, parent, node);
        val = find_below(T, parent, key, len);
    }

    return val;
}
/**
 * Handle overlap on the right of a tree-node
 * @param d the dom in question
 * @param n the node to test against
 * @param r the rogue who overlaps on the right
 */
static void dom_range_overlaps_right( dom *d, node *n, node *r )
{
    if ( dom_mostly_nests(d,node_name(n),node_name(r)) )
    {
        node_split( n, node_offset(r) );
        dom_add_node( d, node_next_sibling(n), r );
    }
    else if ( dom_mostly_nests(d,node_name(r),node_name(n)) )
    {
        node *r2;
        node_split( r, node_end(n) );
        r2 = node_next_sibling(r);
        node_detach_sibling( r, NULL );
        dom_store_range( d, node_to_range(r2) );
        //queue_push( d->q, node_to_range(r2) );
        node_dispose( r2 );
        dom_add_node( d, n, r );
    }
    else
        dom_drop_notify( d, r, n );
}
Exemple #8
0
/**
 * Extend the implicit suffix tree by adding one suffix of the current prefix
 * @param st the current suffixtree
 * @param j the offset into str of the suffix's start
 * @param i the offset into str at the end of the current prefix
 * @param log the log to record errors in
 * @return 1 if the phase continues else 0
 */
static int extension( suffixtree *st, int j, int i, plugin_log *log )
{
    int res = 1;
    pos *p = find_beta( st, j, i-1, log );
    // rule 1 (once a leaf always a leaf)
    if ( node_is_leaf(p->v) && pos_at_edge_end(st,p) )
        res = 1;
    // rule 2
    else if ( !continues(st,p,st->str[i]) )
    {
        //printf("applying rule 2 at j=%d for phase %d\n",j,i);
        node *leaf = node_create_leaf( i, log );
        if ( p->v==st->root || pos_at_edge_end(st,p) )
        {
            node_add_child( p->v, leaf, st->str, log );
            update_current_link( st, p->v );
        }
        else
        {
            node *u = node_split( p->v, p->loc, st->str, log );
            update_current_link( st, u );
            if ( i-j==1 )
            {
                node_set_link( u, st->root );
#ifdef DEBUG
                verify_link( current );
#endif
            }
            else 
                st->current = u;
            node_add_child( u, leaf, st->str, log );
        }
        update_old_beta( st, p, i );
    }
    // rule 3
    else
    {
        //printf("applying rule 3 at j=%d for phase %d\n",j,i);
        update_current_link( st, p->v );
        update_old_beta( st, p, i );
        res = 0;
    }
    free( p );
    return res;
}
Exemple #9
0
/**
 * Extend the implicit suffix tree by adding one suffix of the current prefix
 * @param j the offset into str of the suffix's start
 * @param i the offset into str at the end of the current prefix
 * @return 1 if the phase continues else 0
 */
static int extension( int j, int i )
{
    int res = 1;
    pos *p = find_beta( j, i-1 );
    // rule 1 (once a leaf always a leaf)
    if ( node_is_leaf(p->v) && pos_at_edge_end(p) )
        res = 1;
    // rule 2
    else if ( !continues(p,str[i]) )
    {
        //printf("applying rule 2 at j=%d for phase %d\n",j,i);
        node *leaf = node_create_leaf( i );
        if ( p->v==root || pos_at_edge_end(p) )
        {
            node_add_child( p->v, leaf );
            update_current_link( p->v );
        }
        else
        {
            node *u = node_split( p->v, p->loc );
            update_current_link( u );
            if ( i-j==1 )
            {
                node_set_link( u, root );
#ifdef DEBUG
                verify_link( current );
#endif
            }
            else
                current = u;
            node_add_child( u, leaf );
        }
        update_old_beta( p, i );
    }
    // rule 3
    else
    {
        //printf("applying rule 3 at j=%d for phase %d\n",j,i);
        update_current_link( p->v );
        update_old_beta( p, i );
        res = 0;
    }
    free( p );
    return res;
}
Exemple #10
0
void btree_insert_at(btree_iterator iter, const void *item)
{
	const void *x = item;
	struct btree_node *xr = NULL;
	struct btree_node *p;
	struct btree *btree = iter->btree;

	/* btree_insert_at always sets iter->item to item. */
	iter->item = (void*)item;

	/*
	 * If node is not a leaf, fall to the end of the left branch of item[k]
	 * so that it will be a leaf. This does not modify the iterator's logical
	 * position.
	 */
	if (iter->node->depth)
		branch_end(iter);

	/*
	 * First try inserting item into this node.
	 * If it's too big, split it, and repeat by
	 * trying to insert the median and right subtree into parent.
	 */
	if (iter->node->count < MAX) {
		node_insert(x, xr, iter->node, iter->k);
		goto finished;
	} else {
		for (;;) {
			node_split(&x, &xr, iter->node, iter->k);

			if (!ascend(iter))
				break;

			if (iter->node->count < MAX) {
				node_insert(x, xr, iter->node, iter->k);
				goto finished;
			}
		}

		/*
		 * If splitting came all the way up to the root, create a new root whose
		 * left branch is the current root, median is x, and right branch is the
		 * half split off from the root.
		 */
		assert(iter->node == btree->root);
		p = node_alloc(1);
		p->parent = NULL;
		p->count = 1;
		p->depth = btree->root->depth + 1;
		p->item[0] = x;
		p->branch[0] = btree->root;
			btree->root->parent = p;
			btree->root->k = 0;
		p->branch[1] = xr;
			xr->parent = p;
			xr->k = 1;
		btree->root = p;
	}

finished:
	btree->count++;
	iter->node = NULL;
}