From 46983441ae17b34abee2954b87efeeefbe0768b3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Tue, 1 Jan 2013 09:44:09 +0700 Subject: [PATCH] wildmatch: make a special case for "*/" with FNM_PATHNAME MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Normally we need recursion for "*". In this case we know that it matches everything until "/" so we can skip the recursion. glibc, '*/*/*' on linux-2.6.git file list 2000 times before: wildmatch 8s 74513us fnmatch 1s 97042us or 13.59% faster after: wildmatch 3s 521862us fnmatch 3s 488616us or 99.06% slower Same test with compat/fnmatch: wildmatch 8s 110763us fnmatch 2s 980845us or 36.75% faster wildmatch 3s 522156us fnmatch 1s 544487us or 43.85% slower Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- t/t3070-wildmatch.sh | 8 ++++++++ wildmatch.c | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index 5c9601a0c8..97f1daff8e 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -203,6 +203,10 @@ match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/ match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*' match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t' match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t' +match 0 x foo '*/*/*' +match 0 x foo/bar '*/*/*' +match 1 x foo/bba/arr '*/*/*' +match 0 x foo/bb/aa/rr '*/*/*' pathmatch 1 foo foo pathmatch 0 foo fo @@ -218,5 +222,9 @@ pathmatch 0 foo/bba/arr 'foo/*z' pathmatch 0 foo/bba/arr 'foo/**z' pathmatch 1 foo/bar 'foo?bar' pathmatch 1 foo/bar 'foo[/]bar' +pathmatch 0 foo '*/*/*' +pathmatch 0 foo/bar '*/*/*' +pathmatch 1 foo/bba/arr '*/*/*' +pathmatch 1 foo/bb/aa/rr '*/*/*' test_done diff --git a/wildmatch.c b/wildmatch.c index 536470b794..bb425220b0 100644 --- a/wildmatch.c +++ b/wildmatch.c @@ -117,6 +117,18 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) return WM_NOMATCH; } return WM_MATCH; + } else if (!match_slash && *p == '/') { + /* + * _one_ asterisk followed by a slash + * with WM_PATHNAME matches the next + * directory + */ + const char *slash = strchr((char*)text, '/'); + if (!slash) + return WM_NOMATCH; + text = (const uchar*)slash; + /* the slash is consumed by the top-level for loop */ + break; } while (1) { if (t_ch == '\0') -- 2.11.4.GIT