Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LANG-1548] split regionMatches for better performance #534

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
73 changes: 65 additions & 8 deletions src/main/java/org/apache/commons/lang3/CharSequenceUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -328,17 +328,58 @@ public static char[] toCharArray(final CharSequence source) {
* Green implementation of regionMatches.
*
* @param cs the {@code CharSequence} to be processed
* @param ignoreCase whether or not to be case insensitive
* @param thisStart the index to start on the {@code cs} CharSequence
* @param substring the {@code CharSequence} to be looked for
* @param start the index to start on the {@code substring} CharSequence
* @param length character length of the region
* @return whether the region matched
*/
static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
final CharSequence substring, final int start, final int length) {
static boolean regionMatches(final CharSequence cs, final int thisStart,
final CharSequence substring, final int start, final int length) {
if (cs instanceof String && substring instanceof String) {
return ((String) cs).regionMatches(thisStart, (String) substring, start, length);
}
int index1 = thisStart;
int index2 = start;
int tmpLen = length;

// Extract these first so we detect NPEs the same as the java.lang.String version
final int srcLen = cs.length() - thisStart;
final int otherLen = substring.length() - start;

// Check for invalid parameters
if (thisStart < 0 || start < 0 || length < 0) {
return false;
}

// Check that the regions are long enough
if (srcLen < length || otherLen < length) {
return false;
}

while (tmpLen-- > 0) {
XenoAmess marked this conversation as resolved.
Show resolved Hide resolved
if (cs.charAt(index1++) != substring.charAt(index2++)) {
return false;
}
}

return true;
}

/**
* Green implementation of regionMatches.
*
* @param cs the {@code CharSequence} to be processed
* @param thisStart the index to start on the {@code cs} CharSequence
* @param substring the {@code CharSequence} to be looked for
* @param start the index to start on the {@code substring} CharSequence
* @param length character length of the region
* @return whether the region matched
*/
static boolean regionMatchesIgnoreCase(final CharSequence cs, final int thisStart,
final CharSequence substring, final int start, final int length) {
if (cs instanceof String && substring instanceof String) {
return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
return ((String) cs).regionMatches(true, thisStart, (String) substring, start, length);
}
int index1 = thisStart;
int index2 = start;
Expand Down Expand Up @@ -366,10 +407,6 @@ static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, fi
continue;
}

if (!ignoreCase) {
return false;
}

// The real same check as in String.regionMatches():
final char u1 = Character.toUpperCase(c1);
final char u2 = Character.toUpperCase(c2);
Expand All @@ -380,4 +417,24 @@ static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, fi

return true;
}

/**
* Green implementation of regionMatches.
*
* @param cs the {@code CharSequence} to be processed
* @param ignoreCase whether or not to be case insensitive
* @param thisStart the index to start on the {@code cs} CharSequence
* @param substring the {@code CharSequence} to be looked for
* @param start the index to start on the {@code substring} CharSequence
* @param length character length of the region
* @return whether the region matched
*/
static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
final CharSequence substring, final int start, final int length) {
if (!ignoreCase) {
return regionMatches(cs, thisStart, substring, start, length);
} else {
return regionMatchesIgnoreCase(cs, thisStart, substring, start, length);
}
}
}
8 changes: 4 additions & 4 deletions src/main/java/org/apache/commons/lang3/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ public static boolean containsIgnoreCase(final CharSequence str, final CharSeque
final int len = searchStr.length();
final int max = str.length() - len;
for (int i = 0; i <= max; i++) {
if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) {
if (CharSequenceUtils.regionMatchesIgnoreCase(str, i, searchStr, 0, len)) {
return true;
}
}
Expand Down Expand Up @@ -1909,7 +1909,7 @@ public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequenc
if (cs1.length() != cs2.length()) {
return false;
}
return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length());
return CharSequenceUtils.regionMatchesIgnoreCase(cs1, 0, cs2, 0, cs1.length());
}

/**
Expand Down Expand Up @@ -3165,7 +3165,7 @@ public static int indexOfIgnoreCase(final CharSequence str, final CharSequence s
return startPos;
}
for (int i = startPos; i < endLimit; i++) {
if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
if (CharSequenceUtils.regionMatchesIgnoreCase(str, i, searchStr, 0, searchStr.length())) {
return i;
}
}
Expand Down Expand Up @@ -5168,7 +5168,7 @@ public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequen
}

for (int i = startPos; i >= 0; i--) {
if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStrLength)) {
if (CharSequenceUtils.regionMatchesIgnoreCase(str, i, searchStr, 0, searchStrLength)) {
return i;
}
}
Expand Down