//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); }
//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); }