Commit a277345e05507dfa0a3350d47df96d37063c929f

Russell Belfer 2012-11-14T22:37:13

Create internal strcmp variants for function ptrs Using the builtin strcmp and strcasecmp as function pointers is problematic on win32. This adds internal implementations and divorces us from the platform linkage.

diff --git a/src/diff.c b/src/diff.c
index 6f48d72..d944c65 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -551,15 +551,15 @@ static int diff_list_init_from_iterators(
 	if (!old_iter->ignore_case && !new_iter->ignore_case) {
 		diff->opts.flags &= ~GIT_DIFF_DELTAS_ARE_ICASE;
 
-		diff->strcomp    = strcmp;
-		diff->strncomp   = strncmp;
+		diff->strcomp    = git__strcmp;
+		diff->strncomp   = git__strncmp;
 		diff->pfxcomp    = git__prefixcmp;
 		diff->entrycomp  = git_index_entry__cmp;
 	} else {
 		diff->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE;
 
-		diff->strcomp    = strcasecmp;
-		diff->strncomp   = strncasecmp;
+		diff->strcomp    = git__strcasecmp;
+		diff->strncomp   = git__strncasecmp;
 		diff->pfxcomp    = git__prefixcmp_icase;
 		diff->entrycomp  = git_index_entry__cmp_icase;
 	}
diff --git a/src/pathspec.c b/src/pathspec.c
index 9632f5f..fc6547a 100644
--- a/src/pathspec.c
+++ b/src/pathspec.c
@@ -122,11 +122,11 @@ bool git_pathspec_match_path(
 		fnmatch_flags = FNM_CASEFOLD;
 
 	if (casefold) {
-		use_strcmp  = strcasecmp;
-		use_strncmp = strncasecmp;
+		use_strcmp  = git__strcasecmp;
+		use_strncmp = git__strncasecmp;
 	} else {
-		use_strcmp  = strcmp;
-		use_strncmp = strncmp;
+		use_strcmp  = git__strcmp;
+		use_strncmp = git__strncmp;
 	}
 
 	git_vector_foreach(vspec, i, match) {
diff --git a/src/util.c b/src/util.c
index 7f50438..3a08d45 100644
--- a/src/util.c
+++ b/src/util.c
@@ -174,6 +174,36 @@ int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int ba
 	return error;
 }
 
+int git__strcmp(const char *a, const char *b)
+{
+	while (*a && *b && *a == *b)
+		++a, ++b;
+	return (int)(*(const unsigned char *)a) - (int)(*(const unsigned char *)b);
+}
+
+int git__strcasecmp(const char *a, const char *b)
+{
+	while (*a && *b && tolower(*a) == tolower(*b))
+		++a, ++b;
+	return (tolower(*a) - tolower(*b));
+}
+
+int git__strncmp(const char *a, const char *b, size_t sz)
+{
+	while (sz && *a && *b && *a == *b)
+		--sz, ++a, ++b;
+	if (!sz)
+		return 0;
+	return (int)(*(const unsigned char *)a) - (int)(*(const unsigned char *)b);
+}
+
+int git__strncasecmp(const char *a, const char *b, size_t sz)
+{
+	while (sz && *a && *b && tolower(*a) == tolower(*b))
+		--sz, ++a, ++b;
+	return !sz ? 0 : (tolower(*a) - tolower(*b));
+}
+
 void git__strntolower(char *str, size_t len)
 {
 	size_t i;
diff --git a/src/util.h b/src/util.h
index 23d4bc6..cb1c4fd 100644
--- a/src/util.h
+++ b/src/util.h
@@ -134,6 +134,11 @@ extern int git__bsearch(
 
 extern int git__strcmp_cb(const void *a, const void *b);
 
+extern int git__strcmp(const char *a, const char *b);
+extern int git__strcasecmp(const char *a, const char *b);
+extern int git__strncmp(const char *a, const char *b, size_t sz);
+extern int git__strncasecmp(const char *a, const char *b, size_t sz);
+
 typedef struct {
 	short refcount;
 	void *owner;