Subject: [PATCH v2 4/6] match_{base,path}name: replace strncmp_icase with strnequal_icase

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Sun, 10 Mar 2013 13:14:28 +0700

We could also optimize for ignore_case, assuming that non-ascii
characters are not used in most repositories. We could check that all
patterns and pathnames are ascii-only, then use git's toupper()

        before      after
user    0m0.516s    0m0.433s
user    0m0.523s    0m0.437s
user    0m0.532s    0m0.443s
user    0m0.533s    0m0.448s
user    0m0.535s    0m0.449s
user    0m0.542s    0m0.452s
user    0m0.546s    0m0.453s
user    0m0.551s    0m0.458s
user    0m0.556s    0m0.459s
user    0m0.561s    0m0.462s

Suggested-by: Fredrik Gustafsson <[email-masked]>
Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 dir.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/dir.c b/dir.c
index 46b24db..7b6a625 100644
--- a/dir.c
+++ b/dir.c
@@ -21,6 +21,25 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, in
 	int check_only, const struct path_simplify *simplify);
 static int get_dtype(struct dirent *de, const char *path, int len);
 
+/*
+ * This function is more like memequal_icase than strnequal_icase as
+ * it does not check for NUL. The caller is not supposed to pass a
+ * length longer than both input strings
+ */
+static inline strnequal_icase(const char *a, const char *b, int n)
+{
+	if (!ignore_case) {
+		while (n && *a == *b) {
+			a++;
+			b++;
+			n--;
+		}
+		return n == 0;
+	}
+
+	return !strncmp_icase(a, b, n);
+}
+
 inline int git_fnmatch(const char *pattern, const char *string,
 		       int flags, int prefix)
 {
@@ -611,11 +630,11 @@ int match_basename(const char *basename, int basenamelen,
 {
 	if (prefix == patternlen) {
 		if (patternlen == basenamelen &&
-		    !strncmp_icase(pattern, basename, patternlen))
+		    strnequal_icase(pattern, basename, patternlen))
 			return 1;
 	} else if (flags & EXC_FLAG_ENDSWITH) {
 		if (patternlen - 1 <= basenamelen &&
-		    !strncmp_icase(pattern + 1,
+		    strnequal_icase(pattern + 1,
 				   basename + basenamelen - patternlen + 1,
 				   patternlen - 1))
 			return 1;
@@ -649,7 +668,7 @@ int match_pathname(const char *pathname, int pathlen,
 	 */
 	if (pathlen < baselen + 1 ||
 	    (baselen && (pathname[baselen] != '/' ||
-			 strncmp_icase(pathname, base, baselen))))
+			 !strnequal_icase(pathname, base, baselen))))
 		return 0;
 
 	namelen = baselen ? pathlen - baselen - 1 : pathlen;
@@ -663,7 +682,7 @@ int match_pathname(const char *pathname, int pathlen,
 		if (prefix > namelen)
 			return 0;
 
-		if (strncmp_icase(pattern, name, prefix))
+		if (!strnequal_icase(pattern, name, prefix))
 			return 0;
 		pattern += prefix;
 		name    += prefix;
-- 
1.8.1.2.536.gf441e6d