#include #include #include #include #include #include "fnmatch2.h" #define UINT uint32_t #define UINTSIZE 4 #define FNM_NOMATCH 1 typedef struct { char tp; char chr; } chr_pattern; typedef struct { char tp; UINT chars; } chars_pattern; typedef struct { char tp; } qst_pattern; typedef struct { char tp; char chr; short sizerest; } star_pattern; typedef struct { char tp; } end_pattern; typedef struct { char tp; } endstar_pattern; typedef struct { char tp; char *chars; } bracket_pattern; enum PATTERNS {PATTERN_chr,PATTERN_qst,PATTERN_star,PATTERN_chars,PATTERN_end,PATTERN_endstar,PATTERN_bracket}; union _patterns{ chr_pattern chr;chars_pattern chars;qst_pattern qst;star_pattern star;end_pattern end;endstar_pattern endstar;bracket_pattern bracket; }; typedef union _patterns patterns; struct states{ patterns *p; char pattern_prefix[4]; struct states *next; }; struct _fnmatch_state{ struct states *states; int flags; }; #define NEXTPATTERN(type) pat->chr.tp=PATTERN_##type;pat=(patterns *)(((void *) pat)+sizeof(type##_pattern )); fnmatch_state *fnmatch_compile(char *str,int flags){ unsigned char *s; patterns *pat,*ret; int canpack; int i,m; ret=pat=(patterns *) malloc(200); int rest=0;//compute minimal string size for (s=(unsigned char *)str;*s;s++) { if (*s=='[') { while (*s!=']') s++; }/*] gets counted line below.*/ if (*s!='*') rest++; } for (s=(unsigned char *)str;*s;s++) { switch(*s){ case '*': while (*(s+1)=='?') {/* *?=?* */ NEXTPATTERN(qst) rest--; s++; } if (*(s+1)){ pat->star.sizerest=rest; pat->star.chr=*(s+1); s++; NEXTPATTERN(star) }else{ NEXTPATTERN(endstar) } break; case '?': NEXTPATTERN(qst) rest--; break; case '[': pat->bracket.chars=malloc(255); char *c= pat->bracket.chars; while (*s!=']') *c++=*s++; rest--; NEXTPATTERN(bracket); default: canpack=1; for (i=0;i<4;i++) if (*(s+i)=='*'||*(s+i)=='?') canpack=0; if (canpack){ pat->chars.chars=*((UINT*) s); rest-=UINTSIZE; s+=UINTSIZE-1;//last get added automaticaly. NEXTPATTERN(chars) }else{ pat->chr.chr=*s; rest--; NEXTPATTERN(chr) } break; } } NEXTPATTERN(end) fnmatch_state *st=(fnmatch_state *) malloc(sizeof(fnmatch_state)); st->states=calloc(1,sizeof(struct states)); st->states->p=ret; return st; } #undef NEXTPATTERN #define NEXTPATTERN(type) p=(patterns *)(((void *) p)+sizeof(type##_pattern )); int fnmatch2_internal(patterns *p,char *str,int len){ #include "fnmatch2_loop.h" } char buf[1000]; int fnmatch_exec(fnmatch_state *p, char *str){ char *bu=buf; int i; struct states *s; int len=strlen(str); for (s=p->states;s;s=s->next){ for (i=0;s->pattern_prefix[i];i++){ if(str[i]!=s->pattern_prefix[i]) goto con; } if(!fnmatch2_internal(s->p,str+i,len-i)) return 0; con:; } return FNM_NOMATCH; } #define FNMATCH_PREFIX int fnmatch2_prefix_internal(patterns *p,char *str,int len,fnmatch_state *ret){ #include "fnmatch2_loop.h" } fnmatch_state* fnmatch_prefix(fnmatch_state *p,char *str){ struct states *s; int len=strlen(str),i; fnmatch_state *ret=(fnmatch_state *) calloc(1,sizeof(fnmatch_state)); ret->flags=p->flags; for (s=p->states;s;s=s->next){ for (i=0;s->pattern_prefix[i];i++){ if(str[i]!=s->pattern_prefix[i]) goto con; } fnmatch2_prefix_internal(s->p,str,len,ret); con:; } return ret; } int main(){int i; char ptr[]="*abc*"; int flags=0; fnmatch_state *p=fnmatch_compile(ptr,flags); int cnt=0; char s1[]="abcda", s2[]="bbida",s3[]="nabcx"; for (i=0;i<1000000;i++) { s1[1]++;s2[1]++;s3[1]++; #ifdef COMPARE cnt+=fnmatch(ptr,s1,flags)+fnmatch(ptr,s2,flags)+fnmatch(ptr,s3,flags); #else cnt+=fnmatch_exec(p,s1)+fnmatch_exec(p,s2)+fnmatch_exec(p,s3); #endif } printf("%i\n",cnt); fnmatch_state* s=fnmatch_compile("*foo*",0); fnmatch_state* home=fnmatch_prefix(s,"/home"); fnmatch_state* bar=fnmatch_prefix(s,"/bar"); printf("%i ",fnmatch_exec(home,"foo")); printf("%i ",fnmatch_exec(bar,"foo")); printf("%i ",fnmatch_exec(bar,"bar")); }