/* $Header: /CVSROOT/tinolib/old/strwild.h,v 1.7 2006/08/23 01:19:17 tino Exp $ * * NOTE THAT I THINK IT STILL HAS SOME BUGS! * * Match string against wildcards, returns: 0=match, -1=error, 1=mismatch * * allquantor (*), existquantor (?) and possibilities ([...]) * Variants: * First character ^ inverts content * First matching character can be ], so []] matches ] and [[] matches [ * a-b matches a to b including a and b (a<=b) * b-a matches a to b excluding a and b (a literally * So we have: * [[] is [ [?] is ? * []] is ] [*] is * * [][] is ] or [ [^-] is anything but - * You can use any character instead of [ and ] i. E. \: * \?\ is ? \*\ is * * \\\ is \ (funny) * \\*\ is \ or * */ rev = 0; match = 0; if (*++cmp=='^') { cmp++; rev = 1; } do { if (!*cmp) return -1; if (cmp[1]=='-') { unsigned char from; from = *cmp; cmp += 2; if (!*cmp) return -1; if (from>(unsigned char)*cmp) { if (from>(unsigned char)*s && (unsigned char)*s>(unsigned char)*cmp) match = 1; } else if (from<=(unsigned char)*s && (unsigned char)*s<=(unsigned char)*cmp) match = 1; } else if (*s==*cmp) match = 1; } while (*++cmp!=closeq); if (match!=rev) continue; /* no match, fallthrough */ } else if (*s==*cmp) { if (*cmp) continue; return 0; /* complete match */ } if (!*s) /* *cmp!=0 in this case */ return 1; /* definitively no match */ if (*cmp==existq && existq) continue; /* Other cases left from above: * *cmp==0 and *s!=0 -> no match yet, advance last * * *cmp!=0 and *s!=0 -> different, advance last * */ if (!pos) return 1; /* no previous *, no match */ #if 0 /* Another speedup possible here: * if no * follows, * do a reverse match from the end of the string, * as we have something like '*whatever' */ if (!nextstar) { while (*++cmp!='*') if (!*cmp) return trailmatch(s, wild); nextstar = cmp; } #endif #if 1 cmp = wild; s = ++pos; goto again; /* speedup */ #else cmp = wild-1; s = pos++; #endif } if (!allq) return (*s ? 1 : 0); /* funny special case: no allquantor */ /* we have a * * remember the position * save 'rescan' position (in loop) */ wild = cmp+1; } return 0; /* trailing * match (or empty wildcard matches empty string) */ } static int tino_strwildcmp(const char *s, const char *wild) { return tino_strwild(s, wild, '*', '?', '[', ']'); } #ifdef TINO_TEST_UNIT TEST_1(tino_strwildcmp("a-b-c", "[z")); TEST1(tino_strwildcmp("a-b-c", "*[z]*")); TEST0(tino_strwildcmp("a-b-c", "*[b]*")); TEST0(tino_strwildcmp("a-b-c", "*b*")); TEST0(tino_strwildcmp("a-b-c", "*c")); TEST0(tino_strwildcmp("a-b-c", "a????")); TEST0(tino_strwildcmp("a-b-c", "????c")); TEST0(tino_strwildcmp("a-b-c", "a*")); #endif #ifdef TINO_TEST_MAIN #include int main(int argc, char **argv) { char buf[BUFSIZ*10]; while (fgets(buf, sizeof buf-1, stdin)) { int i; for (i=0; ++i