From f9acb40b9996a848056f51dc8ea9e786ef80a135 Mon Sep 17 00:00:00 2001 From: Henri Yandell Date: Thu, 18 Apr 2013 08:15:47 +0000 Subject: [PATCH] Adding Dmitry Katsubo's patch from LANG-846, providing CharSequenceUtils.regionMatches with a proper green implementation instead of inefficiently converting to Strings git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1469220 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/lang3/CharSequenceUtils.java | 27 ++++++++++++++++--- .../lang3/StringUtilsStartsEndsWithTest.java | 14 ++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java b/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java index 0b096c974..b69e12f52 100644 --- a/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java +++ b/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java @@ -189,9 +189,30 @@ static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, fi if (cs instanceof String && substring instanceof String) { return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length); } else { - // TODO: Implement rather than convert to String - return cs.toString().regionMatches(ignoreCase, thisStart, substring.toString(), start, length); + int index1 = thisStart; + int index2 = start; + int tmpLen = length; + + while (tmpLen-- > 0) { + char c1 = cs.charAt(index1++); + char c2 = substring.charAt(index2++); + + if (c1 == c2) { + continue; + } + + if (!ignoreCase) { + return false; + } + + // The same check as in String.regionMatches(): + if (Character.toUpperCase(c1) != Character.toUpperCase(c2) + && Character.toLowerCase(c1) != Character.toLowerCase(c2)) { + return false; + } + } + + return true; } } - } diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java index d994e8f5c..440793dba 100644 --- a/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java +++ b/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java @@ -120,6 +120,13 @@ public void testEndsWith() { assertTrue("endsWith(FOOBAR, BAR)", StringUtils.endsWith(FOOBAR, BAR)); assertFalse("endsWith(foobar, BAR)", StringUtils.endsWith(foobar, BAR)); assertFalse("endsWith(FOOBAR, bar)", StringUtils.endsWith(FOOBAR, bar)); + + // "alpha,beta,gamma,delta".endsWith("delta") + assertTrue("endsWith(\u03B1\u03B2\u03B3\u03B4, \u03B4)", + StringUtils.endsWith("\u03B1\u03B2\u03B3\u03B4", "\u03B4")); + // "alpha,beta,gamma,delta".endsWith("gamma,DELTA") + assertFalse("endsWith(\u03B1\u03B2\u03B3\u03B4, \u03B3\u0394)", + StringUtils.endsWith("\u03B1\u03B2\u03B3\u03B4", "\u03B3\u0394")); } /** @@ -149,6 +156,13 @@ public void testEndsWithIgnoreCase() { assertTrue(StringUtils.endsWithIgnoreCase("abcdef", "def")); assertTrue(StringUtils.endsWithIgnoreCase("ABCDEF", "def")); assertFalse(StringUtils.endsWithIgnoreCase("ABCDEF", "cde")); + + // "alpha,beta,gamma,delta".endsWith("DELTA") + assertTrue("endsWith(\u03B1\u03B2\u03B3\u03B4, \u0394)", + StringUtils.endsWithIgnoreCase("\u03B1\u03B2\u03B3\u03B4", "\u0394")); + // "alpha,beta,gamma,delta".endsWith("GAMMA") + assertFalse("endsWith(\u03B1\u03B2\u03B3\u03B4, \u0393)", + StringUtils.endsWithIgnoreCase("\u03B1\u03B2\u03B3\u03B4", "\u0393")); } @Test