summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2013-05-30 12:19:10 +0200
committerJunio C Hamano <gitster@pobox.com>2013-06-02 14:13:05 -0700
commitb79c0c3755f3694a3c7ecd3cad18bda011283db7 (patch)
tree70ad6297951c02a5a2d8ae5a9f1fd06beec704c0
parentedca4152560522a431a51fc0a06147fc680b5b18 (diff)
downloadgit-b79c0c3755f3694a3c7ecd3cad18bda011283db7.tar.gz
wildmatch: properly fold case everywhere
Case folding is not done correctly when matching against the [:upper:] character class and uppercased character ranges (e.g. A-Z). Specifically, an uppercase letter fails to match against any of them when case folding is requested because plain characters in the pattern and the whole string are preemptively lowercased to handle the base case fast. That optimization is kept and ISLOWER() is used in the [:upper:] case when case folding is requested, while matching against a character range is retried with toupper() if the character was lowercase, as the bounds of the range itself cannot be modified (in a case-insensitive context, [A-_] is not equivalent to [a-_]). Signed-off-by: Anthony Ramine <n.oxyde@gmail.com> Reviewed-by: Duy Nguyen <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rwxr-xr-xt/t3070-wildmatch.sh55
-rw-r--r--wildmatch.c7
2 files changed, 56 insertions, 6 deletions
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 4c37057ddf..38446a0e87 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -6,20 +6,20 @@ test_description='wildmatch tests'
match() {
if [ $1 = 1 ]; then
- test_expect_success "wildmatch: match '$3' '$4'" "
+ test_expect_success "wildmatch: match '$3' '$4'" "
test-wildmatch wildmatch '$3' '$4'
"
else
- test_expect_success "wildmatch: no match '$3' '$4'" "
+ test_expect_success "wildmatch: no match '$3' '$4'" "
! test-wildmatch wildmatch '$3' '$4'
"
fi
if [ $2 = 1 ]; then
- test_expect_success "fnmatch: match '$3' '$4'" "
+ test_expect_success "fnmatch: match '$3' '$4'" "
test-wildmatch fnmatch '$3' '$4'
"
elif [ $2 = 0 ]; then
- test_expect_success "fnmatch: no match '$3' '$4'" "
+ test_expect_success "fnmatch: no match '$3' '$4'" "
! test-wildmatch fnmatch '$3' '$4'
"
# else
@@ -29,13 +29,25 @@ match() {
fi
}
+imatch() {
+ if [ $1 = 1 ]; then
+ test_expect_success "iwildmatch: match '$2' '$3'" "
+ test-wildmatch iwildmatch '$2' '$3'
+ "
+ else
+ test_expect_success "iwildmatch: no match '$2' '$3'" "
+ ! test-wildmatch iwildmatch '$2' '$3'
+ "
+ fi
+}
+
pathmatch() {
if [ $1 = 1 ]; then
- test_expect_success "pathmatch: match '$2' '$3'" "
+ test_expect_success "pathmatch: match '$2' '$3'" "
test-wildmatch pathmatch '$2' '$3'
"
else
- test_expect_success "pathmatch: no match '$2' '$3'" "
+ test_expect_success "pathmatch: no match '$2' '$3'" "
! test-wildmatch pathmatch '$2' '$3'
"
fi
@@ -235,4 +247,35 @@ pathmatch 1 abcXdefXghi '*X*i'
pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
+# Case-sensitivy features
+match 0 x 'a' '[A-Z]'
+match 1 x 'A' '[A-Z]'
+match 0 x 'A' '[a-z]'
+match 1 x 'a' '[a-z]'
+match 0 x 'a' '[[:upper:]]'
+match 1 x 'A' '[[:upper:]]'
+match 0 x 'A' '[[:lower:]]'
+match 1 x 'a' '[[:lower:]]'
+match 0 x 'A' '[B-Za]'
+match 1 x 'a' '[B-Za]'
+match 0 x 'A' '[B-a]'
+match 1 x 'a' '[B-a]'
+match 0 x 'z' '[Z-y]'
+match 1 x 'Z' '[Z-y]'
+
+imatch 1 'a' '[A-Z]'
+imatch 1 'A' '[A-Z]'
+imatch 1 'A' '[a-z]'
+imatch 1 'a' '[a-z]'
+imatch 1 'a' '[[:upper:]]'
+imatch 1 'A' '[[:upper:]]'
+imatch 1 'A' '[[:lower:]]'
+imatch 1 'a' '[[:lower:]]'
+imatch 1 'A' '[B-Za]'
+imatch 1 'a' '[B-Za]'
+imatch 1 'A' '[B-a]'
+imatch 1 'a' '[B-a]'
+imatch 1 'z' '[Z-y]'
+imatch 1 'Z' '[Z-y]'
+
test_done
diff --git a/wildmatch.c b/wildmatch.c
index 7192bdc1b8..f91ba99f32 100644
--- a/wildmatch.c
+++ b/wildmatch.c
@@ -196,6 +196,11 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
}
if (t_ch <= p_ch && t_ch >= prev_ch)
matched = 1;
+ else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) {
+ uchar t_ch_upper = toupper(t_ch);
+ if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch)
+ matched = 1;
+ }
p_ch = 0; /* This makes "prev_ch" get set to 0. */
} else if (p_ch == '[' && p[1] == ':') {
const uchar *s;
@@ -245,6 +250,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
} else if (CC_EQ(s,i, "upper")) {
if (ISUPPER(t_ch))
matched = 1;
+ else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch))
+ matched = 1;
} else if (CC_EQ(s,i, "xdigit")) {
if (ISXDIGIT(t_ch))
matched = 1;