git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 7/9] wildmatch: make a special case for "*/" with FNM_PATHNAME

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Dec 28, 2012, 04:10 UTC
Message-ID
<1356667854-8686-8-git-send-email-pclouds@gmail.com>
In-Reply-To
<1356667854-8686-1-git-send-email-pclouds@gmail.com>

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 <pclouds@gmail.com>
---
 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 dbfa903..4cdb13b 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 0c8edb8..f6d45d5 100644
--- a/wildmatch.c
+++ b/wildmatch.c
@@ -116,6 +116,18 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
 						return WM_NOMATCH;
 				}
 				return WM_MATCH;
+			} else if (*p == '/' && (flags & WM_PATHNAME) && !match_slash) {
+				/*
+				 * an 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')
-- 
1.8.0.rc2.23.g1fb49df
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 8 of 10 in “fnmatch replacement step 1”
  1. 0/9 fnmatch replacement step 1Nguyễn Thái Ngọc Duy, Dec 28, 2012
  2. 1/9 compat/fnmatch: respect NO_FNMATCH* even on glibcNguyễn Thái Ngọc Duy, Dec 28, 2012
  3. 2/9 wildmatch: replace variable 'special' with better named onesNguyễn Thái Ngọc Duy, Dec 28, 2012
  4. 3/9 wildmatch: rename constants and update prototypeNguyễn Thái Ngọc Duy, Dec 28, 2012
  5. 4/9 wildmatch: make dowild() take arbitrary flagsNguyễn Thái Ngọc Duy, Dec 28, 2012
  6. 5/9 wildmatch: support "no FNM_PATHNAME" modeNguyễn Thái Ngọc Duy, Dec 28, 2012
  7. 6/9 test-wildmatch: add "perf" command to compare wildmatch and fnmatchNguyễn Thái Ngọc Duy, Dec 28, 2012
  8. 7/9 wildmatch: make a special case for "*/" with FNM_PATHNAMENguyễn Thái Ngọc Duy, Dec 28, 2012
  9. 8/9 wildmatch: advance faster in <asterisk> + <literal> patternsNguyễn Thái Ngọc Duy, Dec 28, 2012
  10. 9/9 Makefile: add USE_WILDMATCH to use wildmatch as fnmatchNguyễn Thái Ngọc Duy, Dec 28, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.