On Fri, Mar 22, 2013 at 06:24:39PM -0400, Jeff King wrote: > I'm having trouble figuring out the right solution for this. Thanks for looking into this. It was on my todo list, but you beat me to it :) > But then here we'll end up feeding "foo/" to be compared with "foo", > which we don't want. For a pattern "foo", we want to match _either_ > "foo/" or "foo". So you'd think something like: > > if (pathlen && pathname[pathlen-1] == '/') > pathlen--; > > would work. But it seems that match_basename, despite taking the length > of all of the strings we pass it, will happily use NUL-terminated > functions like strcmp or fnmatch. Converting the former to check lengths > should be pretty straightforward. But there is no version of fnmatch > that does what we want. I wonder if we using wildmatch can get around > this limitation. You can use nwildmatch() from this patch. I tested it lightly with t3070-wildmatch.sh, feeding the strings with no terminating NUL. It seems to work ok. -- 8< -- Subject: [PATCH] wildmatch: do not require "text" to be NUL-terminated This may be helpful when we just want to match a part of "text". nwildmatch can be used for this purpose. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- wildmatch.c | 25 +++++++++++++------------ wildmatch.h | 11 +++++++++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/wildmatch.c b/wildmatch.c index 7192bdc..f97ae2a 100644 --- a/wildmatch.c +++ b/wildmatch.c @@ -52,7 +52,8 @@ typedef unsigned char uchar; #define ISXDIGIT(c) (ISASCII(c) && isxdigit(c)) /* Match pattern "p" against "text" */ -static int dowild(const uchar *p, const uchar *text, unsigned int flags) +static int dowild(const uchar *p, const uchar *text, + const uchar *textend, unsigned int flags) { uchar p_ch; const uchar *pattern = p; @@ -60,8 +61,9 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) for ( ; (p_ch = *p) != '\0'; text++, p++) { int matched, match_slash, negated; uchar t_ch, prev_ch; - if ((t_ch = *text) == '\0' && p_ch != '*') + if (text >= textend && p_ch != '*') return WM_ABORT_ALL; + t_ch = *text; if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) t_ch = tolower(t_ch); if ((flags & WM_CASEFOLD) && ISUPPER(p_ch)) @@ -101,7 +103,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) * both foo/bar and foo/a/bar. */ if (p[0] == '/' && - dowild(p + 1, text, flags) == WM_MATCH) + dowild(p + 1, text, textend, flags) == WM_MATCH) return WM_MATCH; match_slash = 1; } else @@ -130,9 +132,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) /* the slash is consumed by the top-level for loop */ break; } - while (1) { - if (t_ch == '\0') - break; + while (text < textend) { /* * Try to advance faster when an asterisk is * followed by a literal. We know in this case @@ -145,18 +145,18 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) p_ch = *p; if ((flags & WM_CASEFOLD) && ISUPPER(p_ch)) p_ch = tolower(p_ch); - while ((t_ch = *text) != '\0' && + while (text < textend && (match_slash || t_ch != '/')) { if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) t_ch = tolower(t_ch); if (t_ch == p_ch) break; - text++; + t_ch = *++text; } if (t_ch != p_ch) return WM_NOMATCH; } - if ((matched = dowild(p, text, flags)) != WM_NOMATCH) { + if ((matched = dowild(p, text, textend, flags)) != WM_NOMATCH) { if (!match_slash || matched != WM_ABORT_TO_STARSTAR) return matched; } else if (!match_slash && t_ch == '/') @@ -261,12 +261,13 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } } - return *text ? WM_NOMATCH : WM_MATCH; + return text < textend ? WM_NOMATCH : WM_MATCH; } /* Match the "pattern" against the "text" string. */ -int wildmatch(const char *pattern, const char *text, +int nwildmatch(const char *pattern, const char *text, int textlen, unsigned int flags, struct wildopts *wo) { - return dowild((const uchar*)pattern, (const uchar*)text, flags); + return dowild((const uchar*)pattern, (const uchar*)text, + (const uchar*)text + textlen, flags); } diff --git a/wildmatch.h b/wildmatch.h index 4090c8f..cdd7544 100644 --- a/wildmatch.h +++ b/wildmatch.h @@ -12,7 +12,14 @@ struct wildopts; -int wildmatch(const char *pattern, const char *text, - unsigned int flags, +int nwildmatch(const char *pattern, const char *text, + int len, unsigned int flags, struct wildopts *wo); + +/* Match the "pattern" against the "text" string. */ +static inline int wildmatch(const char *pattern, const char *text, + unsigned int flags, struct wildopts *wo) +{ + return nwildmatch(pattern, text, strlen(text), flags, wo); +} #endif -- 1.8.2.83.gc99314b -- 8< -- -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html