/* brand new reg.c -- this one seems to get a fairly consistant 10% gain over the old one. i ripped off the one from IRC servers and edited it to make it work a little better (allows better quoting, and returns a number indicating how closely the string matched, just like the old one). */ #include #include #define tolower(c) (check_case ? c : \ ((((c)>='A') && ((c)<='Z')) ? ((c)-'A'+'a') : c)) /* this is the matches() function from ircd, spaghetti'd up to be more effecient on masks that don't end with a wildcard (ie: hostmask matches). first it does a quick scan of the string in reverse, aborting quickly if any non-wildcard characters don't match. once it comes to the first wildcard, it falls into the reverse-engineered (by fred1) matches function. it's proven to be pretty durn fast. thanks to justin slootsky, who came up with the original idea of running the matches backward (in slightly more complex form). i tried to put lots of comments, cos string matching is not my thing, and i had to sit and think for 5 minutes for every line. (ugh!) */ int wild_matcher(ma,na,check_case) unsigned char *ma, *na; int check_case; { unsigned char *mask=ma, *nask=na, *m=ma, *n=na, *mlast; int close=0,q=0,wild=0; /* take care of null strings (should never match) */ if ((ma==(unsigned char *)0) || (na==(unsigned char *)0)) return 0; if ((!*ma) || (!*na)) return 0; /* find the end of each string */ while (*m) m++; while (*n) n++; m--; n--; mlast=m; /* check the match backwards */ /* while: chars are identical OR the mask char is an unquoted '?' & haven't reached the start of either string & mask char isn't an unquoted '*' */ while (((tolower(*m) == tolower(*n)) || ((*m == '?') && (m[-1]!='\\'))) && (m!=ma) && (n!=na) && !((*m == '*') && (m[-1]!='\\'))) { if (!((*m == '?') && (m[-1]!='\\'))) close++; /* 1 more exact match */ m--; n--; if (*m == '\\') m--; /* if mask was quoting something, skip the \ */ } if ((*m != '*') || (*(m-1)=='\\')) { /* case II - entire string matched, there were no '*' */ if ((m==ma) && (n==na) && (tolower(*m) == tolower(*n))) return close+1; /* case III - one of the strings ended prematurely (no match) */ if ((m==ma) || (n==na)) return 0; /* case IV - failed to match the ending strings, so abort */ return 0; } else { /* case I - hit an unquoted '*' -- fall into matching algorithm */ while (1) { q=(m>mask) ? (*(m-1)=='\\') : 0; /* quoted? */ if (m=mask)) m--; return (mmask) ? (*(m-1)=='\\') : 0; /* quoted? */ if ((*m=='*') && (!q)) { /* unquoted '*' ? */ while ((m>mask)?(*m=='*'):0) m--; /* Throw away the *s */ if (*m=='\\') {m++; q=1;} /* First non-* was quoted, so keep it */ wild=1; ma=m; na=n; } if ((tolower(*m) != tolower(*n)) && ((*m != '?') || q)) { /* non-match */ if (wild) { m=ma; n=--na; q=(m>mask) ? (*(m-1)=='\\') : 0; /* quoted? */ } else return 0; } else { if ((*m!='?') || q) close++; /* Unquoted ?s aren't counted */ if (*m) m--; /* This char got matched */ if (*n) n--; /* This char got matched */ if (q) m--; /* This quote went with the char we matched */ } } } } /* case doesn't matter */ int wild_match(wc,str) char *wc,*str; { return wild_matcher(wc,str,0); } /* case-sensitive match */ int wild_match_case(wc,str) char *wc,*str; { return wild_matcher(wc,str,1); }