diff --git a/src/dclass_client.c b/src/dclass_client.c index 66507d0..b32663c 100644 --- a/src/dclass_client.c +++ b/src/dclass_client.c @@ -1,305 +1,277 @@ /* - * Copyright 2012 The Weather Channel - * Copyright 2013 Reza Naghibi + * Copyright 2012 The Weather Channel Copyright 2013 Reza Naghibi * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * */ - #include "dclass_client.h" +// cnode +typedef struct { + int pos; -//cnode -typedef struct -{ - int pos; + const dtree_dt_node *cn; +} dclass_cnode; - const dtree_dt_node *cn; -} -dclass_cnode; +char **dclass_get_value_pos(dclass_keyvalue *, char *); +static const dclass_keyvalue *dclass_get_kverror(const dclass_index *); +extern unsigned int dtree_hash_char(char); +extern char *dtree_node_path(const dtree_dt_index *, const dtree_dt_node *, + char *); + +// classifies a string +const dclass_keyvalue *dclass_classify(const dclass_index *di, + const char *str) { + int on = 0; + int valid; + int bcvalid; + int i; + int pos = 0; + int rpos = 0; + unsigned int hash; + char buf[DTREE_DATA_BUFLEN]; + const char *p; + const char *token = ""; + packed_ptr pp; + const dtree_dt_node *cnode = NULL; + const dtree_dt_node *wnode = NULL; + const dtree_dt_node *nnode = NULL; + const dtree_dt_node *fbnode; + const dtree_dt_node *fnode; + const dtree_dt_index *h = &di->dti; + dclass_cnode cnodes[DTREE_S_MAX_CHAIN]; + + if (!str || !h->head) + return dclass_get_kverror(di); -char **dclass_get_value_pos(dclass_keyvalue*,char*); -static const dclass_keyvalue *dclass_get_kverror(const dclass_index*); + memset(cnodes, 0, sizeof(cnodes)); -extern unsigned int dtree_hash_char(char); -extern char *dtree_node_path(const dtree_dt_index*,const dtree_dt_node*,char*); - - -//classifies a string -const dclass_keyvalue *dclass_classify(const dclass_index *di,const char *str) -{ - int on=0; - int valid; - int bcvalid; - int i; - int pos=0; - int rpos=0; - unsigned int hash; - char buf[DTREE_DATA_BUFLEN]; - const char *p; - const char *token=""; - packed_ptr pp; - const dtree_dt_node *cnode=NULL; - const dtree_dt_node *wnode=NULL; - const dtree_dt_node *nnode=NULL; - const dtree_dt_node *fbnode; - const dtree_dt_node *fnode; - const dtree_dt_index *h=&di->dti; - dclass_cnode cnodes[DTREE_S_MAX_CHAIN]; - - if(!str || !h->head) - return dclass_get_kverror(di); - - memset(cnodes,0,sizeof(cnodes)); - - dtree_printd(DTREE_PRINT_CLASSIFY,"dclass_classify() UA: '%s'\n",str); - - for(p=str;*p;p++) - { - valid=0; - - hash=dtree_hash_char(*p); - - if(hashflags : 0); + + if (fbnode && dtree_get_flag(h, fbnode, DTREE_DT_FLAG_TOKEN, pos)) { + if ((fnode = dtree_get_flag(h, fbnode, DTREE_DT_FLAG_STRONG, pos))) + return fnode->payload; + else if ((fnode = dtree_get_flag(h, fbnode, DTREE_DT_FLAG_WEAK, pos))) { + i = DTREE_DC_DISTANCE(h, (char *)fnode->payload); + if (!wnode || fnode->rank > wnode->rank || + (fnode->rank == wnode->rank && i >= 0 && + i < DTREE_DC_DISTANCE(h, (char *)wnode->payload))) + wnode = fnode; + } else if ((fnode = + dtree_get_flag(h, fbnode, DTREE_DT_FLAG_NONE, pos))) { + i = DTREE_DC_DISTANCE(h, (char *)fnode->payload); + if (!nnode || + (i >= 0 && i < DTREE_DC_DISTANCE(h, (char *)nnode->payload))) + nnode = fnode; } - - if((!valid || (!*(p+1))) && on) - { - //EOT found - fbnode=dtree_get_node(h,token,0,0); - - dtree_printd(DTREE_PRINT_CLASSIFY,"dtree_classify() token %d(%d): '%s' = '%s':%d\n", - pos,rpos,token,fbnode?dtree_node_path(h,fbnode,buf):"",fbnode?(int)fbnode->flags:0); - - if(fbnode && dtree_get_flag(h,fbnode,DTREE_DT_FLAG_TOKEN,pos)) - { - if((fnode=dtree_get_flag(h,fbnode,DTREE_DT_FLAG_STRONG,pos))) + if ((fnode = dtree_get_flag(h, fbnode, DTREE_DT_FLAG_ACHAIN, pos))) { + pp = fnode->curr; + + while (pp) { + bcvalid = 0; + + if (fnode->flags & DTREE_DT_FLAG_ACHAIN) { + if (fnode->cparam) + dtree_printd( + DTREE_PRINT_CLASSIFY, + "dtree_classify() looking for pchain %p at dir: %d\n", + fnode->cparam, fnode->dir); + else + dtree_printd(DTREE_PRINT_CLASSIFY, + "dtree_classify() pchain candidate %p\n", + fnode->payload); + + for (i = 0; i < DTREE_S_MAX_CHAIN && cnodes[i].cn; i++) { + // chain hit + if (cnodes[i].cn->payload == fnode->cparam && fnode->dir <= 0) { + dtree_printd( + DTREE_PRINT_CLASSIFY, + "dtree_classify() pchain match: %p('%d'):%d %d\n", + cnodes[i].cn->payload, i, cnodes[i].pos, rpos); + + if (fnode->dir < 0 && cnodes[i].pos - rpos < fnode->dir) + continue; + else if (fnode->flags & DTREE_DT_FLAG_BCHAIN) + bcvalid = 1; + else if (!fnode->rank) return fnode->payload; - else if((fnode=dtree_get_flag(h,fbnode,DTREE_DT_FLAG_WEAK,pos))) - { - i=DTREE_DC_DISTANCE(h,(char*)fnode->payload); - if(!wnode || fnode->rank>wnode->rank || (fnode->rank==wnode->rank && - i>=0 && ipayload))) - wnode=fnode; - } - else if((fnode=dtree_get_flag(h,fbnode,DTREE_DT_FLAG_NONE,pos))) - { - i=DTREE_DC_DISTANCE(h,(char*)fnode->payload); - if(!nnode || (i>=0 && ipayload))) - nnode=fnode; + else if (!cnode || fnode->rank > cnode->rank) + cnode = fnode; } - - if((fnode=dtree_get_flag(h,fbnode,DTREE_DT_FLAG_ACHAIN,pos))) - { - pp=fnode->curr; - - while(pp) - { - bcvalid=0; - - if(fnode->flags & DTREE_DT_FLAG_ACHAIN) - { - if(fnode->cparam) - dtree_printd(DTREE_PRINT_CLASSIFY,"dtree_classify() looking for pchain %p at dir: %d\n",fnode->cparam,fnode->dir); - else - dtree_printd(DTREE_PRINT_CLASSIFY,"dtree_classify() pchain candidate %p\n",fnode->payload); - - for(i=0;ipayload==fnode->cparam && fnode->dir<=0) - { - dtree_printd(DTREE_PRINT_CLASSIFY,"dtree_classify() pchain match: %p('%d'):%d %d\n",cnodes[i].cn->payload,i,cnodes[i].pos,rpos); - - if(fnode->dir<0 && cnodes[i].pos-rposdir) - continue; - else if(fnode->flags & DTREE_DT_FLAG_BCHAIN) - bcvalid=1; - else if(!fnode->rank) - return fnode->payload; - else if(!cnode || fnode->rank>cnode->rank) - cnode=fnode; - } - - if(cnodes[i].cn->cparam==fnode->payload && cnodes[i].cn->dir>0) - { - dtree_printd(DTREE_PRINT_CLASSIFY,"dtree_classify() pchain forward match: %p('%d'):%d %d\n",fnode->payload,i,cnodes[i].pos,rpos); - - if(rpos-cnodes[i].pos>cnodes[i].cn->dir) - continue; - //forward chain has a dependency, not implemented - else if(fnode->cparam); - else if(!cnodes[i].cn->rank) - return cnodes[i].cn->payload; - else if(!cnode || cnodes[i].cn->rank>cnode->rank) - cnode=cnodes[i].cn; - } - } - } - - if(fnode->flags & DTREE_DT_FLAG_ACHAIN && (bcvalid || !fnode->cparam || fnode->dir>0)) - { - for(i=0;ipayload,i,rpos); - - break; - } - } - } - - pp=fnode->dup; - fnode=DTREE_DT_GETPP(h,pp); - } + if (cnodes[i].cn->cparam == fnode->payload && + cnodes[i].cn->dir > 0) { + dtree_printd( + DTREE_PRINT_CLASSIFY, + "dtree_classify() pchain forward match: %p('%d'):%d %d\n", + fnode->payload, i, cnodes[i].pos, rpos); + + if (rpos - cnodes[i].pos > cnodes[i].cn->dir) + continue; + // forward chain has a dependency, not implemented + else if (fnode->cparam) + ; + else if (!cnodes[i].cn->rank) + return cnodes[i].cn->payload; + else if (!cnode || cnodes[i].cn->rank > cnode->rank) + cnode = cnodes[i].cn; } + } } - - if(!*(p+1) && posflags & DTREE_DT_FLAG_ACHAIN && + (bcvalid || !fnode->cparam || fnode->dir > 0)) { + for (i = 0; i < DTREE_S_MAX_CHAIN; i++) { + if (!cnodes[i].cn) { + cnodes[i].cn = fnode; + cnodes[i].pos = rpos; + + dtree_printd(DTREE_PRINT_CLASSIFY, + "dtree_classify() pchain added: %p('%d'):%d\n", + fnode->payload, i, rpos); + + break; + } + } } - - on=0; + pp = fnode->dup; + fnode = DTREE_DT_GETPP(h, pp); + } } + } + if (!*(p + 1) && pos < DTREE_S_MAX_POS) { + p--; + + if (token == str) + pos = DTREE_S_BE_POS; + else + pos = DTREE_S_MAX_POS; + + continue; + } + on = 0; } - - if(cnode) - { - if(wnode && wnode->rank>cnode->rank) - return wnode->payload; + } - return cnode->payload; - } - else if(wnode) - return wnode->payload; - else if(nnode) - return nnode->payload; - - return dclass_get_kverror(di); + if (cnode) { + if (wnode && wnode->rank > cnode->rank) + return wnode->payload; + + return cnode->payload; + } else if (wnode) + return wnode->payload; + else if (nnode) + return nnode->payload; + + return dclass_get_kverror(di); } +// gets a string +const dclass_keyvalue *dclass_get(const dclass_index *di, const char *str) { + const dtree_dt_node *node; + const dtree_dt_index *h = &di->dti; -//gets a string -const dclass_keyvalue *dclass_get(const dclass_index *di,const char *str) -{ - const dtree_dt_node *node; - const dtree_dt_index *h=&di->dti; + if (!str || !h->head) + return dclass_get_kverror(di); - if(!str || !h->head) - return dclass_get_kverror(di); + node = dtree_get_node(h, str, DTREE_DT_FLAG_TOKEN, 0); - node=dtree_get_node(h,str,DTREE_DT_FLAG_TOKEN,0); - - if(node && node->payload) - return node->payload; + if (node && node->payload) + return node->payload; - return dclass_get_kverror(di); + return dclass_get_kverror(di); } +// gets the value for a key +const char *dclass_get_kvalue(const dclass_keyvalue *kvd, const char *key) { + int i; -//gets the value for a key -const char *dclass_get_kvalue(const dclass_keyvalue *kvd,const char *key) -{ - int i; - - for(i=0;isize;i++) - { - if(!strcasecmp(kvd->keys[i],key)) - return kvd->values[i]; - } - - return NULL; -} + for (i = 0; i < kvd->size; i++) { + if (!strcasecmp(kvd->keys[i], key)) + return kvd->values[i]; + } -//gets the value pointer for a key -char **dclass_get_value_pos(dclass_keyvalue *kvd,char *key) -{ - int i; - - for(i=0;isize;i++) - { - if(!strcasecmp(kvd->keys[i],key)) - return (char**)&kvd->values[i]; - } - - return NULL; + return NULL; } -//returns an error kvdata -static const dclass_keyvalue *dclass_get_kverror(const dclass_index *di) -{ - return &di->error; -} +// gets the value pointer for a key +char **dclass_get_value_pos(dclass_keyvalue *kvd, char *key) { + int i; + + for (i = 0; i < kvd->size; i++) { + if (!strcasecmp(kvd->keys[i], key)) + return (char **)&kvd->values[i]; + } -//gets the id for a generic payload -const char *dclass_get_id(void *payload) -{ - dclass_keyvalue *kvd; - - kvd=(dclass_keyvalue*)payload; - - return kvd->id; + return NULL; } -//version -const char *dclass_get_version() -{ - return DCLASS_VERSION; +// returns an error kvdata +static const dclass_keyvalue *dclass_get_kverror(const dclass_index *di) { + return &di->error; } -//init -void dclass_init_index(dclass_index *di) -{ - memset(&di->error,0,sizeof(dclass_keyvalue)); +// gets the id for a generic payload +const char *dclass_get_id(void *payload) { + dclass_keyvalue *kvd; - di->error.id=DTREE_M_SERROR; - - dtree_init_index(&di->dti); + kvd = (dclass_keyvalue *)payload; + + return kvd->id; } -//free -void dclass_free(dclass_index *di) -{ - dtree_free(&di->dti); - - dclass_init_index(di); +// version +const char *dclass_get_version() { return DCLASS_VERSION; } + +// init +void dclass_init_index(dclass_index *di) { + memset(&di->error, 0, sizeof(dclass_keyvalue)); + + di->error.id = DTREE_M_SERROR; + + dtree_init_index(&di->dti); } +// free +void dclass_free(dclass_index *di) { + dtree_free(&di->dti); + + dclass_init_index(di); +} diff --git a/src/dclass_client.h b/src/dclass_client.h index e57168f..f26d305 100644 --- a/src/dclass_client.h +++ b/src/dclass_client.h @@ -13,60 +13,48 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * */ - #ifndef _DCLASS_H_INCLUDED_ #define _DCLASS_H_INCLUDED_ - #include "dtree_client.h" +#define DCLASS_VERSION "dClass 2.3.1" -#define DCLASS_VERSION "dClass 2.3.1" +// key value struct, dtree payload +typedef struct { + const char *id; + const char **keys; + const char **values; -//key value struct, dtree payload -typedef struct -{ - const char *id; - - const char **keys; - const char **values; - - unsigned short int size; -} -dclass_keyvalue; + unsigned short int size; +} dclass_keyvalue; +// dclass index +typedef struct { + dtree_dt_index dti; -//dclass index -typedef struct -{ - dtree_dt_index dti; - - dclass_keyvalue error; -} -dclass_index; - + dclass_keyvalue error; +} dclass_index; #include "devicemap_client.h" +void dclass_init_index(dclass_index *); -void dclass_init_index(dclass_index*); - -int dclass_load_file(dclass_index*,const char*); -int dclass_write_file(const dclass_index*,const char*); +int dclass_load_file(dclass_index *, const char *); +int dclass_write_file(const dclass_index *, const char *); -const dclass_keyvalue *dclass_classify(const dclass_index*,const char*); -const dclass_keyvalue *dclass_get(const dclass_index*,const char*); -const char *dclass_get_kvalue(const dclass_keyvalue*,const char*); +const dclass_keyvalue *dclass_classify(const dclass_index *, const char *); +const dclass_keyvalue *dclass_get(const dclass_index *, const char *); +const char *dclass_get_kvalue(const dclass_keyvalue *, const char *); -void dclass_free(dclass_index*); +void dclass_free(dclass_index *); -const char *dclass_get_id(void*); +const char *dclass_get_id(void *); const char *dclass_get_version(); - -#endif /* _DCLASS_H_INCLUDED_ */ +#endif /* _DCLASS_H_INCLUDED_ */ diff --git a/src/dclass_file.c b/src/dclass_file.c index 4b178a6..94c51f9 100644 --- a/src/dclass_file.c +++ b/src/dclass_file.c @@ -13,797 +13,726 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * */ - #include "dclass_client.h" +// structs for parsing dtree file +typedef struct { + char *key; + char *value; -//structs for parsing dtree file -typedef struct -{ - char *key; - char *value; - - size_t key_len; - size_t val_len; -} -dtree_kv_pair; - -typedef struct -{ - char *pattern; - char *id; - char *cparam; - char *type; - - size_t pattern_len; - size_t id_len; - size_t cparam_len; - - int count; - - dtree_flag_f flag; - - unsigned int pos; - unsigned int rank; - signed int dir; - - dtree_kv_pair p[DTREE_DATA_MKEYS]; -} -dtree_file_entry; + size_t key_len; + size_t val_len; +} dtree_kv_pair; +typedef struct { + char *pattern; + char *id; + char *cparam; + char *type; -static void dclass_parse_fentry(char*,dtree_file_entry*,int); -static long dclass_write_tree(const dtree_dt_index*,const dtree_dt_node*,char*,int,FILE*); -static void dclass_write_node(const dtree_dt_node*,char*,FILE*); + size_t pattern_len; + size_t id_len; + size_t cparam_len; -extern unsigned int dtree_hash_char(char); + int count; + dtree_flag_f flag; + + unsigned int pos; + unsigned int rank; + signed int dir; + + dtree_kv_pair p[DTREE_DATA_MKEYS]; +} dtree_file_entry; + +static void dclass_parse_fentry(char *, dtree_file_entry *, int); +static long dclass_write_tree(const dtree_dt_index *, const dtree_dt_node *, + char *, int, FILE *); +static void dclass_write_node(const dtree_dt_node *, char *, FILE *); + +extern unsigned int dtree_hash_char(char); #if DTREE_PERF_WALKING -extern void dtree_timersubn(struct timespec*,struct timespec*,struct timespec*); -extern int dtree_gettime(struct timespec*); +extern void dtree_timersubn(struct timespec *, struct timespec *, + struct timespec *); +extern int dtree_gettime(struct timespec *); #endif +// parses a dtree file +int dclass_load_file(dclass_index *di, const char *path) { + int i, j; + int ret; + int lines = 0; + int keys_size = 0; + char *p; + char *s; + char **keys = NULL; + char buf[10 * 1024]; + FILE *f; + dtree_dt_index ids; + dtree_dt_index *h = &di->dti; + dtree_file_entry fe; + dclass_keyvalue *kvd; + dclass_keyvalue *cparam; + dtree_dt_add_entry entry; -//parses a dtree file -int dclass_load_file(dclass_index *di,const char *path) -{ - int i,j; - int ret; - int lines=0; - int keys_size=0; - char *p; - char *s; - char **keys=NULL; - char buf[10*1024]; - FILE *f; - dtree_dt_index ids; - dtree_dt_index *h=&di->dti; - dtree_file_entry fe; - dclass_keyvalue *kvd; - dclass_keyvalue *cparam; - dtree_dt_add_entry entry; - #if DTREE_PERF_WALKING - struct timespec startn,endn,diffn; - long total,high,low,val,lret; + struct timespec startn, endn, diffn; + long total, high, low, val, lret; #endif - - dclass_init_index(di); - dtree_init_index(&ids); - - dtree_printd(DTREE_PRINT_GENERIC,"DTREE: Loading '%s'\n",path); - - if(!(f=fopen(path,"r"))) - { - fprintf(stderr,"DTREE: cannot open '%s'\n",path); - return -1; + + dclass_init_index(di); + dtree_init_index(&ids); + + dtree_printd(DTREE_PRINT_GENERIC, "DTREE: Loading '%s'\n", path); + + if (!(f = fopen(path, "r"))) { + fprintf(stderr, "DTREE: cannot open '%s'\n", path); + return -1; + } + + // traverse the loadfile + while ((buf[sizeof(buf) - 2] = '\n') && (p = fgets(buf, sizeof(buf), f))) { + lines++; + + // overflow + if (buf[sizeof(buf) - 2] != '\n' && buf[sizeof(buf) - 2]) { + dtree_printd(DTREE_PRINT_INITDTREE, + "LOAD: overflow detected on line %d\n", lines); + + do { + buf[sizeof(buf) - 2] = '\n'; + + if (!fgets(buf, sizeof(buf), f)) + break; + } while (buf[sizeof(buf) - 2] != '\n' && buf[sizeof(buf) - 2]); + + continue; } - - //traverse the loadfile - while((buf[sizeof(buf)-2]='\n') && (p=fgets(buf,sizeof(buf),f))) - { - lines++; - - //overflow - if(buf[sizeof(buf)-2]!='\n' && buf[sizeof(buf)-2]) - { - dtree_printd(DTREE_PRINT_INITDTREE,"LOAD: overflow detected on line %d\n",lines); - - do - { - buf[sizeof(buf)-2]='\n'; - - if(!fgets(buf,sizeof(buf),f)) - break; - } - while(buf[sizeof(buf)-2]!='\n' && buf[sizeof(buf)-2]); - - continue; - } - - if(*buf=='#') - { - switch(*++p) - { - //string order is being forced here - case '!': - for(++p,s=p;*p;p++) - { - if(*p==',' || !*(p+1)) - { - *p='\0'; - s=dtree_alloc_string(h,s,p-s); - dtree_printd(DTREE_PRINT_INITDTREE,"INIT FORCE string: '%s'\n",s); - - kvd=(dclass_keyvalue*)dtree_alloc_mem(h,sizeof(dclass_keyvalue)); - - if(!kvd) - goto lerror; - - kvd->id=s; - - memset(&entry,0,sizeof(dtree_dt_add_entry)); - - entry.data=kvd; - - if(dtree_add_entry(&ids,kvd->id,&entry)<0) - goto lerror; - - dtree_printd(DTREE_PRINT_INITDTREE,"IDS: Successful add: '%s'\n",kvd->id); - - s=(p+1); - } - } - break; - //index params - case '$': - p++; - if(!strncasecmp(p,"partial",6)) - { - h->sflags |= DTREE_S_FLAG_PARTIAL; - dtree_printd(DTREE_PRINT_INITDTREE,"INIT FORCE: partial\n"); - } - else if(!strncasecmp(p,"regex",5)) - { - h->sflags |= DTREE_S_FLAG_REGEX; - dtree_printd(DTREE_PRINT_INITDTREE,"INIT FORCE: regex\n"); - } - else if(!strncasecmp(p,"dups",4)) - { - h->sflags |= DTREE_S_FLAG_DUPS; - dtree_printd(DTREE_PRINT_INITDTREE,"INIT FORCE: dups\n"); - } - else if(!strncasecmp(p,"notrim",6)) - { - h->sflags |= DTREE_S_FLAG_NOTRIM; - dtree_printd(DTREE_PRINT_INITDTREE,"INIT FORCE: notrim\n"); - } - break; - //kv error id - case '@': - p++; - for(s=p;*p;p++) - { - if(*p=='\n') - break; - } - *p='\0'; - di->error.id=dtree_alloc_string(h,s,p-s+1); - //comment - default: - if(!h->comment) - { - if(*p==' ') - p++; - for(s=p;*p;p++) - { - if(*p=='\n') - break; - } - *p='\0'; - h->comment=dtree_alloc_mem(h,(p-s+1)*sizeof(char)); - if(h->comment) - strncpy(h->comment,s,p-s); - } - break; - } - continue; - } - - memset(&fe,0,sizeof(fe)); - - //parse the line - dclass_parse_fentry(buf,&fe,h->sflags & DTREE_S_FLAG_NOTRIM); - - if(!fe.id) - { - dtree_printd(DTREE_PRINT_INITDTREE,"LOAD: bad line detected: '%s':%d\n",buf,lines); - continue; - } - - if(fe.type) - { - for(s=fe.type;*s;s++) - { - if(*s==':') - { - s++; - fe.pos=strtol(s,NULL,10); - break; - } - else if(fe.flag) - continue; - else if(*s=='S') - fe.flag=DTREE_DT_FLAG_STRONG; - else if(*s=='W') - { - fe.flag=DTREE_DT_FLAG_WEAK; - if(*(s+1)>='0' && *(s+1)<='9') - fe.rank=strtol(s+1,NULL,10); - } - else if(*s=='B') - fe.flag=DTREE_DT_FLAG_BCHAIN; - else if(*s=='C') - { - fe.flag=DTREE_DT_FLAG_CHAIN; - if(*(s+1)>='0' && *(s+1)<='9') - fe.rank=strtol(s+1,NULL,10); - } - else if(*s=='N') - fe.flag=DTREE_DT_FLAG_NONE; - } - } - - if(!fe.flag) - fe.flag=DTREE_DT_FLAG_NONE; - - if(fe.cparam) - { - for(s=fe.cparam;*s;s++) - { - if(*s==':') - { - *s='\0'; - - fe.cparam_len=s-fe.cparam; - - fe.dir=strtol(s+1,NULL,10); - } - } - } - if(fe.pos>DTREE_S_BE_POS) - fe.pos=DTREE_S_MAX_POS; - if(fe.rank>DTREE_S_MAX_RANK) - fe.rank=DTREE_S_MAX_RANK; - if(fe.dirDTREE_S_MAX_DIR) - fe.dir=DTREE_S_MAX_DIR; - - if(*fe.pattern==DTREE_PATTERN_BEGIN) - { - fe.pos=1; - fe.pattern++; - fe.pattern_len--; - } + if (*buf == '#') { + switch (*++p) { + // string order is being forced here + case '!': + for (++p, s = p; *p; p++) { + if (*p == ',' || !*(p + 1)) { + *p = '\0'; + s = dtree_alloc_string(h, s, p - s); + dtree_printd(DTREE_PRINT_INITDTREE, "INIT FORCE string: '%s'\n", s); - if(*(fe.pattern+fe.pattern_len-1)==DTREE_PATTERN_END && *(fe.pattern+fe.pattern_len-2)!=DTREE_PATTERN_ESCAPE) - { - if(fe.pos==1) - fe.pos=DTREE_S_BE_POS; - else - fe.pos=DTREE_S_MAX_POS; + kvd = + (dclass_keyvalue *)dtree_alloc_mem(h, sizeof(dclass_keyvalue)); - *(fe.pattern+fe.pattern_len-1)='\0'; - fe.pattern_len--; - } + if (!kvd) + goto lerror; - dtree_printd(DTREE_PRINT_INITDTREE, - "LOAD: line dump: pattern: '%s':%zu id: '%s':%zu type: '%s' flag: %ud cparam: '%s':%zu prd: %d,%d,%d\nKVS", - fe.pattern,fe.pattern_len,fe.id,fe.id_len,fe.type,fe.flag,fe.cparam,fe.cparam_len,fe.pos,fe.rank,fe.dir); - for(i=0;iid=dtree_alloc_string(h,fe.id,fe.id_len); - - memset(&entry,0,sizeof(dtree_dt_add_entry)); - - entry.data=kvd; - - if(dtree_add_entry(&ids,kvd->id,&entry)<0) - goto lerror; - - dtree_printd(DTREE_PRINT_INITDTREE,"IDS: Successful add: '%s'\n",kvd->id); + kvd->id = s; + + memset(&entry, 0, sizeof(dtree_dt_add_entry)); + + entry.data = kvd; + + if (dtree_add_entry(&ids, kvd->id, &entry) < 0) + goto lerror; + + dtree_printd(DTREE_PRINT_INITDTREE, "IDS: Successful add: '%s'\n", + kvd->id); + + s = (p + 1); + } } - - //copy kvs - if(fe.count && !kvd->size) - { - if(fe.count!=keys_size) - { - keys_size=0; - keys=NULL; - } - - if(keys) - { - for(i=0;i=keys_size) - { - keys_size=0; - keys=NULL; - - break; - } - } - } - - if(!keys) - { - dtree_printd(DTREE_PRINT_INITDTREE,"LOAD: allocating new keys count: %d\n",fe.count); - - keys=(char**)dtree_alloc_mem(h,fe.count*sizeof(char*)); - - if(!keys) - goto lerror; - - keys_size=fe.count; - - for(i=0;ikeys=(const char**)keys; - - kvd->size=fe.count; - - kvd->values=(const char**)dtree_alloc_mem(h,kvd->size*sizeof(char*)); - - if(!kvd->values) - goto lerror; - - for(i=0;isize;i++) - { - if(fe.p[i].value) - kvd->values[i]=dtree_alloc_string(h,fe.p[i].value,fe.p[i].val_len); - } + break; + // index params + case '$': + p++; + if (!strncasecmp(p, "partial", 6)) { + h->sflags |= DTREE_S_FLAG_PARTIAL; + dtree_printd(DTREE_PRINT_INITDTREE, "INIT FORCE: partial\n"); + } else if (!strncasecmp(p, "regex", 5)) { + h->sflags |= DTREE_S_FLAG_REGEX; + dtree_printd(DTREE_PRINT_INITDTREE, "INIT FORCE: regex\n"); + } else if (!strncasecmp(p, "dups", 4)) { + h->sflags |= DTREE_S_FLAG_DUPS; + dtree_printd(DTREE_PRINT_INITDTREE, "INIT FORCE: dups\n"); + } else if (!strncasecmp(p, "notrim", 6)) { + h->sflags |= DTREE_S_FLAG_NOTRIM; + dtree_printd(DTREE_PRINT_INITDTREE, "INIT FORCE: notrim\n"); } - - cparam=NULL; - - //lookup cparam - if(fe.cparam && *fe.cparam) - { - dtree_printd(DTREE_PRINT_INITDTREE,"LOAD: cparam detected: '%s':%d\n",fe.cparam,fe.dir); - - cparam=(dclass_keyvalue*)dtree_get(&ids,fe.cparam,0); - - //add cparam - if(!cparam) - { - cparam=(dclass_keyvalue*)dtree_alloc_mem(h,sizeof(dclass_keyvalue)); - - if(!cparam) - goto lerror; - - //populate kvd - cparam->id=dtree_alloc_string(h,fe.cparam,fe.cparam_len); - - memset(&entry,0,sizeof(dtree_dt_add_entry)); - - entry.data=cparam; - - if(dtree_add_entry(&ids,cparam->id,&entry)<0) - goto lerror; - - dtree_printd(DTREE_PRINT_INITDTREE,"IDS: Successful add: '%s'\n",cparam->id); - } + break; + // kv error id + case '@': + p++; + for (s = p; *p; p++) { + if (*p == '\n') + break; } - - memset(&entry,0,sizeof(dtree_dt_add_entry)); - - entry.data=kvd; - entry.flags=fe.flag; - entry.param=cparam; - entry.pos=fe.pos; - entry.rank=fe.rank; - entry.dir=fe.dir; - - //add the entry - ret=dtree_add_entry(h,fe.pattern,&entry); - - if(ret<0) - goto lerror; - else if(ret>0) - dtree_printd(DTREE_PRINT_INITDTREE,"LOAD: Successful add, nodes: %u, size: %lu\n", - h->node_count,h->size); - -#if DTREE_PERF_WALKING - if(!(lines%10)) - { - total=high=low=0; - for(i=0;i<5;i++) - { - dtree_gettime(&startn); - lret=dtree_print(h,NULL); - dtree_gettime(&endn); - dtree_timersubn(&endn,&startn,&diffn); - val=(diffn.tv_sec*1000*1000*1000)+diffn.tv_nsec; - if(diffn.tv_nsec==0 && diffn.tv_sec==0) - { - i--; - continue; - } - if(val>high) - high=val; - if(!i || valnode_count,total/(1000*1000*1000),total/1000000%1000,total/1000%1000,total%1000); + *p = '\0'; + di->error.id = dtree_alloc_string(h, s, p - s + 1); + // comment + default: + if (!h->comment) { + if (*p == ' ') + p++; + for (s = p; *p; p++) { + if (*p == '\n') + break; + } + *p = '\0'; + h->comment = dtree_alloc_mem(h, (p - s + 1) * sizeof(char)); + if (h->comment) + strncpy(h->comment, s, p - s); } -#endif + break; + } + continue; } - - dtree_free(&ids); - fclose(f); - if(!di->error.id || !strcmp(DTREE_M_SERROR,di->error.id)) { - if(DTREE_M_LOOKUP_CACHE && h->dc_cache[0]) - di->error.id=h->dc_cache[0]; - } - - return lines; - -lerror: - - dtree_free(h); - dtree_free(&ids); - fclose(f); - - return -1; -} + memset(&fe, 0, sizeof(fe)); -//parses a line into a file_entry -static void dclass_parse_fentry(char *buf,dtree_file_entry *fe,int notrim) -{ - int count=0; - char sep; - char *p; - char *t; - char *e; - char *key=NULL; - size_t klen=0; - size_t len=0; - - for(p=buf;*p;p++) - { - //start - e=t=p; - - //end - for(;*p;p++) - { - e=p; - len=p-t; - - if((*p==';' && count<4) || ((*p==',' || *p=='=') && count>=4) || *p=='\n') - { - if(!notrim) - { - while((*t==' ' || *t=='\t') && tt) - p--; - - len=p-t; - } - if(*t==DTREE_PATTERN_DQUOTE && p>(t+1) && *(p-1)==DTREE_PATTERN_DQUOTE && *(p-2)!=DTREE_PATTERN_ESCAPE) - { - t++; - *(p-1)='\0'; - len-=2; - } - else if(*t==DTREE_PATTERN_DQUOTE && *p!='\n') - { - if(!notrim) - p=e; - continue; - } - - break; - } - } - - sep=*p; + // parse the line + dclass_parse_fentry(buf, &fe, h->sflags & DTREE_S_FLAG_NOTRIM); - if(!notrim) - sep=*e; + if (!fe.id) { + dtree_printd(DTREE_PRINT_INITDTREE, "LOAD: bad line detected: '%s':%d\n", + buf, lines); + continue; + } - *p='\0'; + if (fe.type) { + for (s = fe.type; *s; s++) { + if (*s == ':') { + s++; + fe.pos = strtol(s, NULL, 10); + break; + } else if (fe.flag) + continue; + else if (*s == 'S') + fe.flag = DTREE_DT_FLAG_STRONG; + else if (*s == 'W') { + fe.flag = DTREE_DT_FLAG_WEAK; + if (*(s + 1) >= '0' && *(s + 1) <= '9') + fe.rank = strtol(s + 1, NULL, 10); + } else if (*s == 'B') + fe.flag = DTREE_DT_FLAG_BCHAIN; + else if (*s == 'C') { + fe.flag = DTREE_DT_FLAG_CHAIN; + if (*(s + 1) >= '0' && *(s + 1) <= '9') + fe.rank = strtol(s + 1, NULL, 10); + } else if (*s == 'N') + fe.flag = DTREE_DT_FLAG_NONE; + } + } - p=e; + if (!fe.flag) + fe.flag = DTREE_DT_FLAG_NONE; - if(strlen(t)!=len) - dtree_printd(DTREE_PRINT_INITDTREE,"LOAD: ERROR: '%s' != %zu\n",t,len); + if (fe.cparam) { + for (s = fe.cparam; *s; s++) { + if (*s == ':') { + *s = '\0'; - if(!count) - { - fe->pattern=t; - fe->pattern_len=len; - } - else if(count==1) - { - fe->id=t; - fe->id_len=len; - } - else if(count==2) - fe->type=t; - else if(count==3) - { - fe->cparam=t; - fe->cparam_len=len; - } - else if(count>=4) - { - if(!key) - { - key=t; - klen=len; - - if(sep==',') - { - t=NULL; - len=0; - } - else - continue; - } - - fe->p[fe->count].key=key; - fe->p[fe->count].key_len=klen; - fe->p[fe->count].value=t; - fe->p[fe->count].val_len=len; - - fe->count++; - - if(fe->count>=DTREE_DATA_MKEYS) - break; - - key=NULL; + fe.cparam_len = s - fe.cparam; + + fe.dir = strtol(s + 1, NULL, 10); } - - count++; + } } -} -//writes a dtree file -int dclass_write_file(const dclass_index *di,const char *outFile) -{ - int lines=0; - unsigned int i; - char buf[DTREE_DATA_BUFLEN]; - FILE *f; - const dtree_dt_index *h=&di->dti; - - if(!(f=fopen(outFile,"w"))) - { - fprintf(stderr,"DTREE: cannot open '%s'\n",outFile); - return -1; + if (fe.pos > DTREE_S_BE_POS) + fe.pos = DTREE_S_MAX_POS; + if (fe.rank > DTREE_S_MAX_RANK) + fe.rank = DTREE_S_MAX_RANK; + if (fe.dir < DTREE_S_MIN_DIR) + fe.dir = DTREE_S_MIN_DIR; + else if (fe.dir > DTREE_S_MAX_DIR) + fe.dir = DTREE_S_MAX_DIR; + + if (*fe.pattern == DTREE_PATTERN_BEGIN) { + fe.pos = 1; + fe.pattern++; + fe.pattern_len--; } - - if(h->comment) - { - fputs("# ",f); - fputs(h->comment,f); - fputc('\n',f); + + if (*(fe.pattern + fe.pattern_len - 1) == DTREE_PATTERN_END && + *(fe.pattern + fe.pattern_len - 2) != DTREE_PATTERN_ESCAPE) { + if (fe.pos == 1) + fe.pos = DTREE_S_BE_POS; + else + fe.pos = DTREE_S_MAX_POS; + + *(fe.pattern + fe.pattern_len - 1) = '\0'; + fe.pattern_len--; + } + + dtree_printd(DTREE_PRINT_INITDTREE, + "LOAD: line dump: pattern: '%s':%zu id: '%s':%zu type: '%s' " + "flag: %ud cparam: '%s':%zu prd: %d,%d,%d\nKVS", + fe.pattern, fe.pattern_len, fe.id, fe.id_len, fe.type, fe.flag, + fe.cparam, fe.cparam_len, fe.pos, fe.rank, fe.dir); + for (i = 0; i < fe.count; i++) + dtree_printd(DTREE_PRINT_INITDTREE, ",'%s':%zu='%s':%zu", fe.p[i].key, + fe.p[i].key_len, fe.p[i].value, fe.p[i].val_len); + dtree_printd(DTREE_PRINT_INITDTREE, "\n"); + + // look for this entry + kvd = (dclass_keyvalue *)dtree_get(&ids, fe.id, 0); + + if (!kvd) { + kvd = (dclass_keyvalue *)dtree_alloc_mem(h, sizeof(dclass_keyvalue)); + + if (!kvd) + goto lerror; + + // populate kvd + kvd->id = dtree_alloc_string(h, fe.id, fe.id_len); + + memset(&entry, 0, sizeof(dtree_dt_add_entry)); + + entry.data = kvd; + + if (dtree_add_entry(&ids, kvd->id, &entry) < 0) + goto lerror; + + dtree_printd(DTREE_PRINT_INITDTREE, "IDS: Successful add: '%s'\n", + kvd->id); + } + + // copy kvs + if (fe.count && !kvd->size) { + if (fe.count != keys_size) { + keys_size = 0; + keys = NULL; + } + + if (keys) { + for (i = 0; i < fe.count; i++) { + for (j = 0; j < keys_size; j++) { + if (!strcasecmp(fe.p[i].key, keys[j])) + break; + } + + if (j >= keys_size) { + keys_size = 0; + keys = NULL; + + break; + } + } + } + + if (!keys) { + dtree_printd(DTREE_PRINT_INITDTREE, + "LOAD: allocating new keys count: %d\n", fe.count); + + keys = (char **)dtree_alloc_mem(h, fe.count * sizeof(char *)); + + if (!keys) + goto lerror; + + keys_size = fe.count; + + for (i = 0; i < fe.count; i++) + keys[i] = dtree_alloc_string(h, fe.p[i].key, fe.p[i].key_len); + } + + kvd->keys = (const char **)keys; + + kvd->size = fe.count; + + kvd->values = + (const char **)dtree_alloc_mem(h, kvd->size * sizeof(char *)); + + if (!kvd->values) + goto lerror; + + for (i = 0; i < kvd->size; i++) { + if (fe.p[i].value) + kvd->values[i] = + dtree_alloc_string(h, fe.p[i].value, fe.p[i].val_len); + } } - else - fputs("# dtree dump\n",f); - - if(h->sflags & DTREE_S_FLAG_PARTIAL) - fputs("#$partial\n",f); - - if(h->sflags & DTREE_S_FLAG_REGEX) - fputs("#$regex\n",f); - - if(h->sflags & DTREE_S_FLAG_DUPS) - fputs("#$dups\n",f); - - if(di->error.id && strcmp(DTREE_M_SERROR,di->error.id)) { - fputs("#@",f); - fputs(di->error.id,f); - fputc('\n',f); + + cparam = NULL; + + // lookup cparam + if (fe.cparam && *fe.cparam) { + dtree_printd(DTREE_PRINT_INITDTREE, "LOAD: cparam detected: '%s':%d\n", + fe.cparam, fe.dir); + + cparam = (dclass_keyvalue *)dtree_get(&ids, fe.cparam, 0); + + // add cparam + if (!cparam) { + cparam = (dclass_keyvalue *)dtree_alloc_mem(h, sizeof(dclass_keyvalue)); + + if (!cparam) + goto lerror; + + // populate kvd + cparam->id = dtree_alloc_string(h, fe.cparam, fe.cparam_len); + + memset(&entry, 0, sizeof(dtree_dt_add_entry)); + + entry.data = cparam; + + if (dtree_add_entry(&ids, cparam->id, &entry) < 0) + goto lerror; + + dtree_printd(DTREE_PRINT_INITDTREE, "IDS: Successful add: '%s'\n", + cparam->id); + } } - //dump cache - if(h->dc_cache[0]) - { - fputs("#!",f); - for(i=0;h->dc_cache[i] && idc_cache[i],f); + memset(&entry, 0, sizeof(dtree_dt_add_entry)); + + entry.data = kvd; + entry.flags = fe.flag; + entry.param = cparam; + entry.pos = fe.pos; + entry.rank = fe.rank; + entry.dir = fe.dir; + + // add the entry + ret = dtree_add_entry(h, fe.pattern, &entry); + + if (ret < 0) + goto lerror; + else if (ret > 0) + dtree_printd(DTREE_PRINT_INITDTREE, + "LOAD: Successful add, nodes: %u, size: %lu\n", + h->node_count, h->size); + +#if DTREE_PERF_WALKING + if (!(lines % 10)) { + total = high = low = 0; + for (i = 0; i < 5; i++) { + dtree_gettime(&startn); + lret = dtree_print(h, NULL); + dtree_gettime(&endn); + dtree_timersubn(&endn, &startn, &diffn); + val = (diffn.tv_sec * 1000 * 1000 * 1000) + diffn.tv_nsec; + if (diffn.tv_nsec == 0 && diffn.tv_sec == 0) { + i--; + continue; } - fputc('\n',f); + if (val > high) + high = val; + if (!i || val < low) + low = val; + total += val; + } + total = (total - high - low) / 3; + printf("walk tree: %ld tokens %zu nodes time: %lds %ldms %ldus %ldns\n", + lret, h->node_count, total / (1000 * 1000 * 1000), + total / 1000000 % 1000, total / 1000 % 1000, total % 1000); } - - for(i=0;h->head && ihead->nodes[i]),buf,0,f); - - fclose(f); - - return lines; +#endif + } + + dtree_free(&ids); + fclose(f); + + if (!di->error.id || !strcmp(DTREE_M_SERROR, di->error.id)) { + if (DTREE_M_LOOKUP_CACHE && h->dc_cache[0]) + di->error.id = h->dc_cache[0]; + } + + return lines; + +lerror: + + dtree_free(h); + dtree_free(&ids); + fclose(f); + + return -1; } -static long dclass_write_tree(const dtree_dt_index *h,const dtree_dt_node *n,char *path,int depth,FILE *f) -{ - unsigned int i; - long tot=0; - packed_ptr pp; - const dtree_dt_node *dupn; - - if(!n || !n->curr || depth>(DTREE_DATA_BUFLEN-1)) - return 0; - - if(h->sflags & DTREE_S_FLAG_REGEX) - { - switch(n->data) - { - case DTREE_PATTERN_ANY: - pp=n->prev; - dupn=DTREE_DT_GETPP(h,pp); - i=dtree_hash_char(n->data); - if(i==DTREE_HASH_ANY || (pp && dupn->nodes[i]!=n->curr)) - break; - case DTREE_PATTERN_OPTIONAL: - case DTREE_PATTERN_SET_S: - case DTREE_PATTERN_SET_E: - case DTREE_PATTERN_GROUP_S: - case DTREE_PATTERN_GROUP_E: - case DTREE_PATTERN_ESCAPE: - case DTREE_PATTERN_DQUOTE: - path[depth]=DTREE_PATTERN_ESCAPE; - depth++; +// parses a line into a file_entry +static void dclass_parse_fentry(char *buf, dtree_file_entry *fe, int notrim) { + int count = 0; + char sep; + char *p; + char *t; + char *e; + char *key = NULL; + size_t klen = 0; + size_t len = 0; + + for (p = buf; *p; p++) { + // start + e = t = p; + + // end + for (; *p; p++) { + e = p; + len = p - t; + + if ((*p == ';' && count < 4) || + ((*p == ',' || *p == '=') && count >= 4) || *p == '\n') { + if (!notrim) { + while ((*t == ' ' || *t == '\t') && t < p) + t++; + while ((*(p - 1) == ' ' || *(p - 1) == '\t') && p > t) + p--; + + len = p - t; + } + if (*t == DTREE_PATTERN_DQUOTE && p > (t + 1) && + *(p - 1) == DTREE_PATTERN_DQUOTE && + *(p - 2) != DTREE_PATTERN_ESCAPE) { + t++; + *(p - 1) = '\0'; + len -= 2; + } else if (*t == DTREE_PATTERN_DQUOTE && *p != '\n') { + if (!notrim) + p = e; + continue; } - } - path[depth]=n->data; - path[depth+1]='\0'; - - if(n->flags & DTREE_DT_FLAG_TOKEN) - { - dclass_write_node(n,path,f); - - tot++; + break; + } } - - pp=n->dup; - dupn=DTREE_DT_GETPP(h,pp); - - while(pp) - { - dclass_write_node(dupn,path,f); - - tot++; - - pp=dupn->dup; - dupn=DTREE_DT_GETPP(h,pp); - } - - for(i=0;inodes[i]) - tot+=dclass_write_tree(h,DTREE_DT_GETPP(h,n->nodes[i]),path,depth+1,f); + + sep = *p; + + if (!notrim) + sep = *e; + + *p = '\0'; + + p = e; + + if (strlen(t) != len) + dtree_printd(DTREE_PRINT_INITDTREE, "LOAD: ERROR: '%s' != %zu\n", t, len); + + if (!count) { + fe->pattern = t; + fe->pattern_len = len; + } else if (count == 1) { + fe->id = t; + fe->id_len = len; + } else if (count == 2) + fe->type = t; + else if (count == 3) { + fe->cparam = t; + fe->cparam_len = len; + } else if (count >= 4) { + if (!key) { + key = t; + klen = len; + + if (sep == ',') { + t = NULL; + len = 0; + } else + continue; + } + + fe->p[fe->count].key = key; + fe->p[fe->count].key_len = klen; + fe->p[fe->count].value = t; + fe->p[fe->count].val_len = len; + + fe->count++; + + if (fe->count >= DTREE_DATA_MKEYS) + break; + + key = NULL; } - - path[depth]='\0'; - if(path[depth-1]==DTREE_PATTERN_ESCAPE) - path[depth-1]='\0'; - - return tot; + count++; + } } -static void dclass_write_node(const dtree_dt_node *n,char *path,FILE *f) -{ - int i; - dclass_keyvalue *s; - - s=(dclass_keyvalue*)n->payload; - - fputc(DTREE_PATTERN_DQUOTE,f); - - fputs(path,f); - - fputc(DTREE_PATTERN_DQUOTE,f); - fputc(';',f); - fputc(DTREE_PATTERN_DQUOTE,f); - - fputs(s->id,f); - - fputc(DTREE_PATTERN_DQUOTE,f); - fputc(';',f); - - if(n->flags & DTREE_DT_FLAG_STRONG) - fputc('S',f); - else if(n->flags & DTREE_DT_FLAG_WEAK) - { - fputc('W',f); - if(n->rank) - fprintf(f,"%hd",(short int)n->rank); - } - else if(n->flags & DTREE_DT_FLAG_BCHAIN) - fputc('B',f); - else if(n->flags & DTREE_DT_FLAG_CHAIN) - { - fputc('C',f); - if(n->rank) - fprintf(f,"%hd",(short int)n->rank); +// writes a dtree file +int dclass_write_file(const dclass_index *di, const char *outFile) { + int lines = 0; + unsigned int i; + char buf[DTREE_DATA_BUFLEN]; + FILE *f; + const dtree_dt_index *h = &di->dti; + + if (!(f = fopen(outFile, "w"))) { + fprintf(stderr, "DTREE: cannot open '%s'\n", outFile); + return -1; + } + + if (h->comment) { + fputs("# ", f); + fputs(h->comment, f); + fputc('\n', f); + } else + fputs("# dtree dump\n", f); + + if (h->sflags & DTREE_S_FLAG_PARTIAL) + fputs("#$partial\n", f); + + if (h->sflags & DTREE_S_FLAG_REGEX) + fputs("#$regex\n", f); + + if (h->sflags & DTREE_S_FLAG_DUPS) + fputs("#$dups\n", f); + + if (di->error.id && strcmp(DTREE_M_SERROR, di->error.id)) { + fputs("#@", f); + fputs(di->error.id, f); + fputc('\n', f); + } + + // dump cache + if (h->dc_cache[0]) { + fputs("#!", f); + for (i = 0; h->dc_cache[i] && i < DTREE_M_LOOKUP_CACHE; i++) { + if (i && !(i % 8)) + fputs("\n#!", f); + else if (i) + fputc(',', f); + fputs(h->dc_cache[i], f); } - else - fputc('N',f); - - if(n->pos) - fprintf(f,":%hd",(short int)n->pos); - - fputc(';',f); - - if(n->cparam) - { - fputc(DTREE_PATTERN_DQUOTE,f); - fputs(((dclass_keyvalue*)n->cparam)->id,f); - if(n->dir) - fprintf(f,":%d",n->dir); - fputc(DTREE_PATTERN_DQUOTE,f); + fputc('\n', f); + } + + for (i = 0; h->head && i < DTREE_HASH_NCOUNT; i++) + lines += + dclass_write_tree(h, DTREE_DT_GETPP(h, h->head->nodes[i]), buf, 0, f); + + fclose(f); + + return lines; +} + +static long dclass_write_tree(const dtree_dt_index *h, const dtree_dt_node *n, + char *path, int depth, FILE *f) { + unsigned int i; + long tot = 0; + packed_ptr pp; + const dtree_dt_node *dupn; + + if (!n || !n->curr || depth > (DTREE_DATA_BUFLEN - 1)) + return 0; + + if (h->sflags & DTREE_S_FLAG_REGEX) { + switch (n->data) { + case DTREE_PATTERN_ANY: + pp = n->prev; + dupn = DTREE_DT_GETPP(h, pp); + i = dtree_hash_char(n->data); + if (i == DTREE_HASH_ANY || (pp && dupn->nodes[i] != n->curr)) + break; + case DTREE_PATTERN_OPTIONAL: + case DTREE_PATTERN_SET_S: + case DTREE_PATTERN_SET_E: + case DTREE_PATTERN_GROUP_S: + case DTREE_PATTERN_GROUP_E: + case DTREE_PATTERN_ESCAPE: + case DTREE_PATTERN_DQUOTE: + path[depth] = DTREE_PATTERN_ESCAPE; + depth++; } - - fputc(';',f); - - for(i=0;isize;i++) - { - if(i) - fputc(',',f); - fputc(DTREE_PATTERN_DQUOTE,f); - fputs(s->keys[i],f); - fputc(DTREE_PATTERN_DQUOTE,f); - if(s->values[i]) - { - fputc('=',f); - fputc(DTREE_PATTERN_DQUOTE,f); - fputs(s->values[i],f); - fputc(DTREE_PATTERN_DQUOTE,f); - } + } + + path[depth] = n->data; + path[depth + 1] = '\0'; + + if (n->flags & DTREE_DT_FLAG_TOKEN) { + dclass_write_node(n, path, f); + + tot++; + } + + pp = n->dup; + dupn = DTREE_DT_GETPP(h, pp); + + while (pp) { + dclass_write_node(dupn, path, f); + + tot++; + + pp = dupn->dup; + dupn = DTREE_DT_GETPP(h, pp); + } + + for (i = 0; i < DTREE_HASH_NCOUNT; i++) { + if (n->nodes[i]) + tot += dclass_write_tree(h, DTREE_DT_GETPP(h, n->nodes[i]), path, + depth + 1, f); + } + + path[depth] = '\0'; + + if (path[depth - 1] == DTREE_PATTERN_ESCAPE) + path[depth - 1] = '\0'; + + return tot; +} + +static void dclass_write_node(const dtree_dt_node *n, char *path, FILE *f) { + int i; + dclass_keyvalue *s; + + s = (dclass_keyvalue *)n->payload; + + fputc(DTREE_PATTERN_DQUOTE, f); + + fputs(path, f); + + fputc(DTREE_PATTERN_DQUOTE, f); + fputc(';', f); + fputc(DTREE_PATTERN_DQUOTE, f); + + fputs(s->id, f); + + fputc(DTREE_PATTERN_DQUOTE, f); + fputc(';', f); + + if (n->flags & DTREE_DT_FLAG_STRONG) + fputc('S', f); + else if (n->flags & DTREE_DT_FLAG_WEAK) { + fputc('W', f); + if (n->rank) + fprintf(f, "%hd", (short int)n->rank); + } else if (n->flags & DTREE_DT_FLAG_BCHAIN) + fputc('B', f); + else if (n->flags & DTREE_DT_FLAG_CHAIN) { + fputc('C', f); + if (n->rank) + fprintf(f, "%hd", (short int)n->rank); + } else + fputc('N', f); + + if (n->pos) + fprintf(f, ":%hd", (short int)n->pos); + + fputc(';', f); + + if (n->cparam) { + fputc(DTREE_PATTERN_DQUOTE, f); + fputs(((dclass_keyvalue *)n->cparam)->id, f); + if (n->dir) + fprintf(f, ":%d", n->dir); + fputc(DTREE_PATTERN_DQUOTE, f); + } + + fputc(';', f); + + for (i = 0; i < s->size; i++) { + if (i) + fputc(',', f); + fputc(DTREE_PATTERN_DQUOTE, f); + fputs(s->keys[i], f); + fputc(DTREE_PATTERN_DQUOTE, f); + if (s->values[i]) { + fputc('=', f); + fputc(DTREE_PATTERN_DQUOTE, f); + fputs(s->values[i], f); + fputc(DTREE_PATTERN_DQUOTE, f); } - - fputc('\n',f); + } + + fputc('\n', f); } diff --git a/src/devicemap_client.c b/src/devicemap_client.c index b9b0d95..635a2b6 100644 --- a/src/devicemap_client.c +++ b/src/devicemap_client.c @@ -13,599 +13,581 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * */ - #include "dclass_client.h" - -//devicemap property keys +// devicemap property keys static const char *devicemap_key_array[] = DEVICEMAP_KEYS; - -static int devicemap_read_device_raw(FILE*,dtree_dt_index*,dtree_dt_index*); -static int devicemap_read_pattern(FILE*,dtree_dt_index*,dtree_dt_index*,dtree_flag_f*); -static int devicemap_add_device_pattern(dtree_dt_index*,dtree_dt_index*,dclass_keyvalue*,dclass_keyvalue*,char*,dtree_flag_f); -static const char *devicemap_copy_string(dtree_dt_index*,const char*,const char*); -static int devicemap_alloc_kvd(dtree_dt_index*,dtree_dt_index*,char*); -static char *devicemap_get_attr(const char*,const char*,dtree_dt_index*,char**,char*); -static char *devicemap_get_value(const char*,const char*,dtree_dt_index*,char**,char*); -static char *devicemap_get_str(const char*,const char*,dtree_dt_index*,char**,char*,char*,char); -static char *devicemap_unregex(const char*,char*); +static int devicemap_read_device_raw(FILE *, dtree_dt_index *, + dtree_dt_index *); +static int devicemap_read_pattern(FILE *, dtree_dt_index *, dtree_dt_index *, + dtree_flag_f *); +static int devicemap_add_device_pattern(dtree_dt_index *, dtree_dt_index *, + dclass_keyvalue *, dclass_keyvalue *, + char *, dtree_flag_f); +static const char *devicemap_copy_string(dtree_dt_index *, const char *, + const char *); +static int devicemap_alloc_kvd(dtree_dt_index *, dtree_dt_index *, char *); +static char *devicemap_get_attr(const char *, const char *, dtree_dt_index *, + char **, char *); +static char *devicemap_get_value(const char *, const char *, dtree_dt_index *, + char **, char *); +static char *devicemap_get_str(const char *, const char *, dtree_dt_index *, + char **, char *, char *, char); +static char *devicemap_unregex(const char *, char *); #if OPENDDR_BLKBRY_FIX -static void openddr_convert_bb(char*); +static void openddr_convert_bb(char *); #endif -extern char **dclass_get_value_pos(dclass_keyvalue*,char*); - - -//loads devicemap resources -int devicemap_load_resources(dclass_index *di,const char *path) -{ - int i; - int ret; - int dcount=0; - int pcount=0; - char fpath[1024]; - FILE *f=NULL; - dtree_flag_f flags=0; - dtree_dt_index dev; - dtree_dt_index *h=&di->dti; - - dclass_init_index(di); - dtree_init_index(&dev); - - h->sflags=DTREE_S_FLAG_REGEX|DTREE_S_FLAG_DUPS; - - //string and device cache - di->error.id=dtree_alloc_string(h,"unknown",7); - - if(!devicemap_alloc_kvd(h,&dev,"genericPhone") || !devicemap_alloc_kvd(h,&dev,"genericAndroid") || - !devicemap_alloc_kvd(h,&dev,"desktopDevice")) +extern char **dclass_get_value_pos(dclass_keyvalue *, char *); + +// loads devicemap resources +int devicemap_load_resources(dclass_index *di, const char *path) { + int i; + int ret; + int dcount = 0; + int pcount = 0; + char fpath[1024]; + FILE *f = NULL; + dtree_flag_f flags = 0; + dtree_dt_index dev; + dtree_dt_index *h = &di->dti; + + dclass_init_index(di); + dtree_init_index(&dev); + + h->sflags = DTREE_S_FLAG_REGEX | DTREE_S_FLAG_DUPS; + + // string and device cache + di->error.id = dtree_alloc_string(h, "unknown", 7); + + if (!devicemap_alloc_kvd(h, &dev, "genericPhone") || + !devicemap_alloc_kvd(h, &dev, "genericAndroid") || + !devicemap_alloc_kvd(h, &dev, "desktopDevice")) + goto dexit; + + dtree_alloc_string(h, "true", 4); + dtree_alloc_string(h, "false", 5); + + // build a device tree + for (i = 0; i < 2; i++) { + if (!i) + sprintf(fpath, "%s/%s", path, DEVICEMAP_RSRC_DD); + else + sprintf(fpath, "%s/%s", path, DEVICEMAP_RSRC_DDP); + + dtree_printd(DTREE_PRINT_GENERIC, "DeviceMap device data: '%s'\n", fpath); + + if (!(f = fopen(fpath, "r"))) { + fprintf(stderr, "DeviceMap: cannot open '%s'\n", fpath); + if (!i) goto dexit; - - dtree_alloc_string(h,"true",4); - dtree_alloc_string(h,"false",5); - - //build a device tree - for(i=0;i<2;i++) - { - if(!i) - sprintf(fpath,"%s/%s",path,DEVICEMAP_RSRC_DD); - else - sprintf(fpath,"%s/%s",path,DEVICEMAP_RSRC_DDP); - - dtree_printd(DTREE_PRINT_GENERIC,"DeviceMap device data: '%s'\n",fpath); - - if(!(f=fopen(fpath,"r"))) - { - fprintf(stderr,"DeviceMap: cannot open '%s'\n",fpath); - if(!i) - goto dexit; - } + } - while((ret=devicemap_read_device_raw(f,h,&dev))) - { - if(ret==-1) - goto dexit; - - dcount++; - } + while ((ret = devicemap_read_device_raw(f, h, &dev))) { + if (ret == -1) + goto dexit; - fclose(f); + dcount++; } - - dtree_printd(DTREE_PRINT_INITDTREE,"DeviceMap device data raw count: %d\n",dcount); - - dtree_printd(DTREE_PRINT_INITDTREE,"Open DDR raw dtree stats: nodes: %zu slabs: %zu mem: %zu bytes strings: %zu(%zu,%zu)\n", - dev.node_count,dev.slab_count,dev.size,dev.dc_count,dev.dc_slab_count,dev.dc_slab_pos); - - //build main pattern tree - for(i=0;i<2;i++) - { - if(!i) - sprintf(fpath,"%s/%s",path,DEVICEMAP_RSRC_BD); - else - sprintf(fpath,"%s/%s",path,DEVICEMAP_RSRC_BDP); - - dtree_printd(DTREE_PRINT_GENERIC,"DeviceMap builder data: '%s'\n",fpath); - - if(!(f=fopen(fpath,"r"))) - { - fprintf(stderr,"DeviceMap: cannot open '%s'\n",fpath); - if(!i) - goto dexit; - } - while((ret=devicemap_read_pattern(f,h,&dev,&flags))) - { - if(ret==-1) - goto dexit; - - pcount++; - } + fclose(f); + } + + dtree_printd(DTREE_PRINT_INITDTREE, "DeviceMap device data raw count: %d\n", + dcount); + + dtree_printd(DTREE_PRINT_INITDTREE, + "Open DDR raw dtree stats: nodes: %zu slabs: %zu mem: %zu bytes " + "strings: %zu(%zu,%zu)\n", + dev.node_count, dev.slab_count, dev.size, dev.dc_count, + dev.dc_slab_count, dev.dc_slab_pos); + + // build main pattern tree + for (i = 0; i < 2; i++) { + if (!i) + sprintf(fpath, "%s/%s", path, DEVICEMAP_RSRC_BD); + else + sprintf(fpath, "%s/%s", path, DEVICEMAP_RSRC_BDP); + + dtree_printd(DTREE_PRINT_GENERIC, "DeviceMap builder data: '%s'\n", fpath); + + if (!(f = fopen(fpath, "r"))) { + fprintf(stderr, "DeviceMap: cannot open '%s'\n", fpath); + if (!i) + goto dexit; + } + + while ((ret = devicemap_read_pattern(f, h, &dev, &flags))) { + if (ret == -1) + goto dexit; - fclose(f); + pcount++; } - - dtree_printd(DTREE_PRINT_INITDTREE,"DeviceMap pattern data raw count: %d\n",pcount); - - dtree_free(&dev); - - return pcount; - + + fclose(f); + } + + dtree_printd(DTREE_PRINT_INITDTREE, "DeviceMap pattern data raw count: %d\n", + pcount); + + dtree_free(&dev); + + return pcount; + dexit: - if(f) - fclose(f); + if (f) + fclose(f); + + dtree_free(&dev); + dtree_free(h); + dclass_init_index(di); - dtree_free(&dev); - dtree_free(h); - dclass_init_index(di); - - return -1; + return -1; } -//read a device from file, return it -static int devicemap_read_device_raw(FILE *f,dtree_dt_index *h,dtree_dt_index *dev) -{ - int i; - int ret=0; - char buf[1048]; - char temp[DTREE_DATA_BUFLEN]; - dclass_keyvalue *kvd=NULL; - dtree_dt_add_entry entry; - - if(!f) - return 0; - - while((buf[sizeof(buf)-2]='\n') && fgets(buf,sizeof(buf),f)) - { - //overflow - if(buf[sizeof(buf)-2]!='\n' && buf[sizeof(buf)-2]) - { - dtree_printd(DTREE_PRINT_INITDTREE,"DEVICEMAP LOAD: overflow detected\n"); - - do - { - buf[sizeof(buf)-2]='\n'; - - if(!fgets(buf,sizeof(buf),f)) - break; - } - while(buf[sizeof(buf)-2]!='\n' && buf[sizeof(buf)-2]); - - continue; - } - - if(strstr(buf,"size=sizeof(devicemap_key_array)/sizeof(*devicemap_key_array); - kvd->keys=devicemap_key_array; - - kvd->values=(const char**)dtree_alloc_mem(h,sizeof(devicemap_key_array)); - - if(!kvd->values) - return -1; - - kvd->id=dtree_alloc_string(h,temp,strlen(temp)); - - devicemap_get_attr(buf,"parentId",h,dclass_get_value_pos(kvd,"parentId"),NULL); - - ret=1; - - if(strstr(buf,"/>")) - break; - } - else if(strstr(buf,"")) - break; - else if(kvd && strstr(buf," ",kvd,kvd->id,kvd->id); - for(i=0;isize;i++) - dtree_printd(DTREE_PRINT_INITDTREE,"%s: '%s' ",kvd->keys[i],kvd->values[i]); - dtree_printd(DTREE_PRINT_INITDTREE,"\n"); - memset(&entry,0,sizeof(dtree_dt_add_entry)); + if (strstr(buf, "size = sizeof(devicemap_key_array) / sizeof(*devicemap_key_array); + kvd->keys = devicemap_key_array; + + kvd->values = + (const char **)dtree_alloc_mem(h, sizeof(devicemap_key_array)); + + if (!kvd->values) + return -1; - entry.data=kvd; + kvd->id = dtree_alloc_string(h, temp, strlen(temp)); - //add to device tree - if(dtree_add_entry(dev,kvd->id,&entry)<0) - return -1; + devicemap_get_attr(buf, "parentId", h, + dclass_get_value_pos(kvd, "parentId"), NULL); + + ret = 1; + + if (strstr(buf, "/>")) + break; + } else if (strstr(buf, "")) + break; + else if (kvd && strstr(buf, " ", kvd, kvd->id, + kvd->id); + for (i = 0; i < kvd->size; i++) + dtree_printd(DTREE_PRINT_INITDTREE, "%s: '%s' ", kvd->keys[i], + kvd->values[i]); + dtree_printd(DTREE_PRINT_INITDTREE, "\n"); + + memset(&entry, 0, sizeof(dtree_dt_add_entry)); + + entry.data = kvd; + + // add to device tree + if (dtree_add_entry(dev, kvd->id, &entry) < 0) + return -1; + } + + return ret; } -//read a pattern from file, insert it -static int devicemap_read_pattern(FILE *f,dtree_dt_index *h,dtree_dt_index *dev,dtree_flag_f *flags) -{ - int ret=0; - char buf[1048]; - char pattern[DTREE_DATA_BUFLEN]; - char id[DTREE_DATA_BUFLEN]; - dclass_keyvalue *der=NULL; - dclass_keyvalue *chain=NULL; - const dtree_dt_node *base; - +// read a pattern from file, insert it +static int devicemap_read_pattern(FILE *f, dtree_dt_index *h, + dtree_dt_index *dev, dtree_flag_f *flags) { + int ret = 0; + char buf[1048]; + char pattern[DTREE_DATA_BUFLEN]; + char id[DTREE_DATA_BUFLEN]; + dclass_keyvalue *der = NULL; + dclass_keyvalue *chain = NULL; + const dtree_dt_node *base; + #if OPENDDR_BLKBRY_FIX - dtree_flag_f bb_flag; - dclass_keyvalue *bb_chain; + dtree_flag_f bb_flag; + dclass_keyvalue *bb_chain; #endif - - if(!f) - return 0; - - while((buf[sizeof(buf)-2]='\n') && fgets(buf,sizeof(buf),f)) - { - //overflow - if(buf[sizeof(buf)-2]!='\n' && buf[sizeof(buf)-2]) - { - dtree_printd(DTREE_PRINT_INITDTREE,"DEVICEMAP LOAD: overflow detected\n"); - - do - { - buf[sizeof(buf)-2]='\n'; - - if(!fgets(buf,sizeof(buf),f)) - break; - } - while(buf[sizeof(buf)-2]!='\n' && buf[sizeof(buf)-2]); - - continue; - } - if(strstr(buf,"