//adds an entry to the tree
int dtree_add_entry(dtree_dt_index *h,const char *key,dtree_dt_add_entry *entry)
{
    char namebuf[DTREE_DATA_BUFLEN+1];
    packed_ptr pp;
    
    if(!key)
        return 0;

    *namebuf='\0';
    namebuf[sizeof(namebuf)-1]='\0';
    
    strncpy(namebuf+1,key,sizeof(namebuf)-1);
    
    if(namebuf[sizeof(namebuf)-1])
        return 0;
    
    dtree_printd(DTREE_PRINT_INITDTREE,"ADD ENTRY: name '%s':%d\n",namebuf+1,entry->flags);
    
    if(!h->head)
    {
        pp=dtree_alloc_node(h);
        
        if(!pp)
        {
            fprintf(stderr,"DTREE: allocation error detected, aborting: %zu\n",h->node_count);
            return -1;
        }
        
        h->head=DTREE_DT_GETPP(h,pp);
        h->head->curr=pp;
        h->head->data=0;
    }
    
    if(!entry->flags)
        entry->flags=DTREE_DT_FLAG_STRONG;
    
    return dtree_add_node(h,h->head,namebuf+1,entry);
}
//adds a node to the tree
static int dtree_add_node(dtree_dt_index *h,dtree_dt_node *n,char *t,const dtree_dt_add_entry *entry)
{
    int hash;
    char *s;
    packed_ptr pp;
    dtree_dt_node *next;
    
    if(!n)
        return 0;
    
    dtree_printd(DTREE_PRINT_INITDTREE,"ADD: tree: '%c' level: %d t: '%s' p(%p) pp(%p)\n",
             n->data?n->data:'^',dtree_node_depth(h,n),t,n,n->curr);
    
    //escape
    if(h->sflags & DTREE_S_FLAG_REGEX && (*t==DTREE_PATTERN_ESCAPE) && *(t-1)!=DTREE_PATTERN_ESCAPE)
        t++;

    //(abc)
    while(h->sflags & DTREE_S_FLAG_REGEX && (*t==DTREE_PATTERN_GROUP_S || *t==DTREE_PATTERN_GROUP_E) &&
            *(t-1)!=DTREE_PATTERN_ESCAPE)
    {
        hash=(*t==DTREE_PATTERN_GROUP_S);
        s=t+1;

        while(*s && hash)
        {
            if(*s==DTREE_PATTERN_GROUP_S && *(s-1)!=DTREE_PATTERN_ESCAPE)
                hash++;
            else if(*s==DTREE_PATTERN_GROUP_E && *(s-1)!=DTREE_PATTERN_ESCAPE)
                hash--;

            s++;
        }

        if(*t==DTREE_PATTERN_GROUP_S)
        {
            dtree_printd(DTREE_PRINT_INITDTREE,"ADD: group detected: '%c' - '%c'\n",*(t+1)?*(t+1):'#',*s?*s:'#');

            //optional group
            if(*s==DTREE_PATTERN_OPTIONAL && *(s-1)!=DTREE_PATTERN_ESCAPE)
            {
                if(dtree_add_node(h,n,s+1,entry)<0)
                    return -1;
            }
        }

        t++;
    }

    //?
    if(h->sflags & DTREE_S_FLAG_REGEX && *t==DTREE_PATTERN_OPTIONAL && *(t-1)!=DTREE_PATTERN_ESCAPE)
    {
        //no group
        if(*(t-1)!=DTREE_PATTERN_GROUP_E || *(t-2)==DTREE_PATTERN_ESCAPE)
        {
            pp=n->prev;
            next=DTREE_DT_GETPP(h,pp);
        
            if(!pp)
                return 0;
        
            dtree_printd(DTREE_PRINT_INITDTREE,"ADD: optional: '%c' t: '%s'\n",next->data?next->data:'^',(t+1));
        
            if(dtree_add_node(h,next,t+1,entry)<0)
                return -1;
        }

        t++;

        return dtree_add_node(h,n,t,entry);
    }

    //EOT
    if(!*t && n->prev)
        return dtree_set_payload(h,n,entry);
    
    //[abc]
    if(h->sflags & DTREE_S_FLAG_REGEX && *t==DTREE_PATTERN_SET_S && *(t-1)!=DTREE_PATTERN_ESCAPE)
    {
        for(s=t;*s;s++)
        {
            if(*s==DTREE_PATTERN_SET_E && *(s-1)!=DTREE_PATTERN_ESCAPE)
                break;
        }
        
        if(!*s)
            return 0;
        
        t++;
        
        while(t<s)
        {
            *s=*t;
            
            dtree_printd(DTREE_PRINT_INITDTREE,"ADD: set: '%c' *t: '%c' t: '%s'\n",n->data?n->data:'^',*t,s);
            
            if(dtree_add_node(h,n,s,entry)<0)
                return -1;
            
            t++;
        }
        
        *s=DTREE_PATTERN_SET_E;
        
        return 1;
    }
    
    hash=dtree_hash_char(*t);
        
    if(!hash && *t!='0')
        return 0;
        
    if(*t>='A' && *t<='Z')
        *t|=0x20;
        
    //.
    if(h->sflags & DTREE_S_FLAG_REGEX && *t==DTREE_PATTERN_ANY && *(t-1)!=DTREE_PATTERN_ESCAPE)
        hash=DTREE_HASH_ANY;
        
    pp=(packed_ptr)n->nodes[hash];
    next=DTREE_DT_GETPP(h,pp);
        
    if(!pp)
    {
        pp=dtree_alloc_node(h);
        next=DTREE_DT_GETPP(h,pp);
        
        if(!pp)
        {
            fprintf(stderr,"DTREE: allocation error detected, aborting: %zu\n",h->node_count);
            return -1;
        }
        
        if(hash==DTREE_HASH_ANY)
            next->data=DTREE_PATTERN_ANY;
        else
            next->data=*t;

        next->curr=pp;
        next->prev=n->curr;
        
        n->nodes[hash]=pp;
        
        dtree_printd(DTREE_PRINT_INITDTREE,"ADD: new node '%c' created level: %d hash: %d p(%p) pp(%p)\n",
                 *t,dtree_node_depth(h,n),hash,next,pp);
    }
    
    //EOT
    if(!*(t+1))
        return dtree_set_payload(h,next,entry);

    return dtree_add_node(h,next,t+1,entry);
}
Exemple #3
0
//adds a node to the tree
static int dtree_add_node(dtree_dt_index *h,dtree_dt_node *n,char *t,void *data,flag_f flags,void *param)
{
    int hash;
    char *p;
    packed_ptr pp;
    dtree_dt_node *next;
    
    if(!n)
        return 0;
    
    dtree_printd(DTREE_PRINT_INITDTREE,"ADD: tree: '%c' level: %d *t: '%c' p(%p) pp(%p)\n",
             n->data,dtree_node_depth(h,n),*t?*t:'#',n,n->curr);
    
    //EOT trailing wildcard
    if(!*t && n->prev)
        return dtree_set_payload(h,n,data,flags,param);
        
    //?
    if(h->sflags & DTREE_S_FLAG_REGEX && *t==DTREE_PATTERN_OPTIONAL)
    {
        pp=n->prev;
        next=DTREE_DT_GETPP(h,pp);
        
        if(!pp)
            return 0;
        
        dtree_printd(DTREE_PRINT_INITDTREE,"ADD: optional: '%c' *t: '%c'\n",next->data,*(t+1));
        
        if(dtree_add_node(h,next,t+1,data,flags,param)<0)
            return -1;
        
        t++;
        
        //trailing wildcard
        if(!*t)
            return dtree_set_payload(h,n,data,flags,param);
    }
    
    //[abc]
    if(h->sflags & DTREE_S_FLAG_REGEX && *t==DTREE_PATTERN_SET_S)
    {
        for(p=t;*p;p++)
        {
            if(*p==DTREE_PATTERN_SET_E)
                break;
        }
        
        if(!*p)
            return 0;
        
        t++;
        
        while(t<p)
        {
            *p=*t;
            
            dtree_printd(DTREE_PRINT_INITDTREE,"ADD: set: '%c' *t: '%c' t: '%s'\n",n->data,*t,p);
            
            if(dtree_add_node(h,n,p,data,flags,param)<0)
                return -1;
            
            t++;
        }
        
        *p=DTREE_PATTERN_SET_E;
        
        return 1;
    }
    
    hash=dtree_hash_char(*t);
        
    if(!hash && *t!='0')
        return 0;
        
    if(*t>='A' && *t<='Z')
        *t|=0x20;
        
    //.
    if(hash==DTREE_HASH_ANY)
        *t=DTREE_PATTERN_ANY;
        
    pp=(packed_ptr)n->nodes[hash];
    next=DTREE_DT_GETPP(h,pp);
        
    if(!pp)
    {
        pp=dtree_alloc_node(h);
        next=DTREE_DT_GETPP(h,pp);
        
        if(!pp)
        {
            fprintf(stderr,"DTREE: allocation error detected, aborting: %zu\n",h->node_count);
            return -1;
        }
        
        next->data=*t;
        next->curr=pp;
        next->prev=n->curr;
        
        n->nodes[hash]=pp;
        
        dtree_printd(DTREE_PRINT_INITDTREE,"ADD: new node '%c' created level: %d hash: %d p(%p) pp(%p)\n",
                 *t,dtree_node_depth(h,n),hash,next,pp);
    }
    
    //EOT
    if(!*(t+1))
        return dtree_set_payload(h,next,data,flags,param);

    return dtree_add_node(h,next,t+1,data,flags,param);
}