implement FNM_CASEFOLD extension to fnmatch function

This commit is contained in:
Nagy Szabolcs 2014-10-10 12:09:03 +02:00 committed by Rich Felker
parent aac59c1164
commit efa9d396f9
1 changed files with 25 additions and 11 deletions

View File

@ -97,7 +97,13 @@ escaped:
return pat[0]; return pat[0];
} }
static int match_bracket(const char *p, int k) static int casefold(int k)
{
int c = towupper(k);
return c == k ? towlower(k) : c;
}
static int match_bracket(const char *p, int k, int kfold)
{ {
wchar_t wc; wchar_t wc;
int inv = 0; int inv = 0;
@ -119,7 +125,10 @@ static int match_bracket(const char *p, int k)
wchar_t wc2; wchar_t wc2;
int l = mbtowc(&wc2, p+1, 4); int l = mbtowc(&wc2, p+1, 4);
if (l < 0) return 0; if (l < 0) return 0;
if (wc<=wc2 && (unsigned)k-wc <= wc2-wc) return !inv; if (wc <= wc2)
if ((unsigned)k-wc <= wc2-wc ||
(unsigned)kfold-wc <= wc2-wc)
return !inv;
p += l-1; p += l-1;
continue; continue;
} }
@ -132,7 +141,9 @@ static int match_bracket(const char *p, int k)
char buf[16]; char buf[16];
memcpy(buf, p0, p-1-p0); memcpy(buf, p0, p-1-p0);
buf[p-1-p0] = 0; buf[p-1-p0] = 0;
if (iswctype(k, wctype(buf))) return !inv; if (iswctype(k, wctype(buf)) ||
iswctype(kfold, wctype(buf)))
return !inv;
} }
continue; continue;
} }
@ -143,7 +154,7 @@ static int match_bracket(const char *p, int k)
if (l < 0) return 0; if (l < 0) return 0;
p += l-1; p += l-1;
} }
if (wc==k) return !inv; if (wc==k || wc==kfold) return !inv;
} }
return inv; return inv;
} }
@ -153,7 +164,7 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n
const char *p, *ptail, *endpat; const char *p, *ptail, *endpat;
const char *s, *stail, *endstr; const char *s, *stail, *endstr;
size_t pinc, sinc, tailcnt=0; size_t pinc, sinc, tailcnt=0;
int c, k; int c, k, kfold;
if (flags & FNM_PERIOD) { if (flags & FNM_PERIOD) {
if (*str == '.' && *pat != '.') if (*str == '.' && *pat != '.')
@ -173,10 +184,11 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n
return (c==END) ? 0 : FNM_NOMATCH; return (c==END) ? 0 : FNM_NOMATCH;
str += sinc; str += sinc;
n -= sinc; n -= sinc;
kfold = flags & FNM_CASEFOLD ? casefold(k) : k;
if (c == BRACKET) { if (c == BRACKET) {
if (!match_bracket(pat, k)) if (!match_bracket(pat, k, kfold))
return FNM_NOMATCH; return FNM_NOMATCH;
} else if (c != QUESTION && k != c) { } else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH; return FNM_NOMATCH;
} }
pat+=pinc; pat+=pinc;
@ -233,10 +245,11 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n
break; break;
} }
s += sinc; s += sinc;
kfold = flags & FNM_CASEFOLD ? casefold(k) : k;
if (c == BRACKET) { if (c == BRACKET) {
if (!match_bracket(p-pinc, k)) if (!match_bracket(p-pinc, k, kfold))
return FNM_NOMATCH; return FNM_NOMATCH;
} else if (c != QUESTION && k != c) { } else if (c != QUESTION && k != c && kfold != c) {
return FNM_NOMATCH; return FNM_NOMATCH;
} }
} }
@ -261,10 +274,11 @@ static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n
k = str_next(s, endstr-s, &sinc); k = str_next(s, endstr-s, &sinc);
if (!k) if (!k)
return FNM_NOMATCH; return FNM_NOMATCH;
kfold = flags & FNM_CASEFOLD ? casefold(k) : k;
if (c == BRACKET) { if (c == BRACKET) {
if (!match_bracket(p-pinc, k)) if (!match_bracket(p-pinc, k, kfold))
break; break;
} else if (c != QUESTION && k != c) { } else if (c != QUESTION && k != c && kfold != c) {
break; break;
} }
s += sinc; s += sinc;