Find unicode support (IDEA-112749)

This commit is contained in:
Maxim.Mossienko
2016-09-16 13:01:41 +02:00
parent b7a5f1eceb
commit 92513ba6ae
2 changed files with 60 additions and 19 deletions
@@ -31,6 +31,7 @@ public class StringSearcher {
private final int myPatternLength;
private final int[] mySearchTable = new int[128];
private final boolean myCaseSensitive;
private final boolean myLowecaseTransform;
private final boolean myForwardDirection;
private final boolean myJavaIdentifier;
private final boolean myHandleEscapeSequences;
@@ -57,7 +58,14 @@ public class StringSearcher {
myPattern = pattern;
myCaseSensitive = caseSensitive;
myForwardDirection = forwardDirection;
myPatternArray = myCaseSensitive ? myPattern.toCharArray() : myPattern.toLowerCase(Locale.US).toCharArray();
char[] chars = myCaseSensitive ? myPattern.toCharArray() : myPattern.toLowerCase(Locale.US).toCharArray();
if (chars.length != myPattern.length()) {
myLowecaseTransform = false;
chars = myPattern.toUpperCase(Locale.US).toCharArray();
} else {
myLowecaseTransform = true;
}
myPatternArray = chars;
myPatternLength = myPatternArray.length;
Arrays.fill(mySearchTable, -1);
myJavaIdentifier = lookForJavaIdentifiersOnlyIfPossible &&
@@ -113,18 +121,13 @@ public class StringSearcher {
while (start <= end) {
int i = myPatternLength - 1;
char lastChar = textArray != null ? textArray[start + i] : text.charAt(start + i);
if (!myCaseSensitive) {
lastChar = StringUtil.toLowerCase(lastChar);
}
if (myPatternArray[i] == lastChar) {
char lastChar = normalizedCharAt(text, textArray, start + i);
if (isSameChar(myPatternArray[i], lastChar)) {
i--;
while (i >= 0) {
char c = textArray != null ? textArray[start + i] : text.charAt(start + i);
if (!myCaseSensitive) {
c = StringUtil.toLowerCase(c);
}
if (myPatternArray[i] != c) break;
if (!isSameChar(myPatternArray[i], c)) break;
i--;
}
if (i < 0) {
@@ -152,18 +155,13 @@ public class StringSearcher {
int end = _end + 1;
while (start <= end - myPatternLength + 1) {
int i = myPatternLength - 1;
char lastChar = textArray != null ? textArray[end - (start + i)] : text.charAt(end - (start + i));
if (!myCaseSensitive) {
lastChar = StringUtil.toLowerCase(lastChar);
}
if (myPatternArray[myPatternLength - 1 - i] == lastChar) {
char lastChar = normalizedCharAt(text, textArray, end - (start + i));
if (isSameChar(myPatternArray[myPatternLength - 1 - i], lastChar)) {
i--;
while (i >= 0) {
char c = textArray != null ? textArray[end - (start + i)] : text.charAt(end - (start + i));
if (!myCaseSensitive) {
c = StringUtil.toLowerCase(c);
}
if (myPatternArray[myPatternLength - 1 - i] != c) break;
if (!isSameChar(myPatternArray[myPatternLength - 1 - i], c)) break;
i--;
}
if (i < 0) return end - start - myPatternLength + 1;
@@ -186,6 +184,22 @@ public class StringSearcher {
}
}
private char normalizedCharAt(@NotNull CharSequence text, @Nullable char[] textArray, int index) {
char lastChar = textArray != null ? textArray[index] : text.charAt(index);
if (myCaseSensitive) {
return lastChar;
}
return myLowecaseTransform ? StringUtil.toLowerCase(lastChar) : StringUtil.toUpperCase(lastChar);
}
private boolean isSameChar(char charInPattern, char charInText) {
boolean sameChar = charInPattern == charInText;
if (!sameChar && !myCaseSensitive) {
return StringUtil.charsEqualIgnoreCase(charInPattern, charInText);
}
return sameChar;
}
/**
* @deprecated Use {@link #scan(CharSequence)} instead
*/
@@ -207,6 +221,7 @@ public class StringSearcher {
StringSearcher searcher = (StringSearcher)o;
if (myCaseSensitive != searcher.myCaseSensitive) return false;
if (myLowecaseTransform != searcher.myLowecaseTransform) return false;
if (myForwardDirection != searcher.myForwardDirection) return false;
if (myJavaIdentifier != searcher.myJavaIdentifier) return false;
if (myHandleEscapeSequences != searcher.myHandleEscapeSequences) return false;
@@ -217,6 +232,7 @@ public class StringSearcher {
public int hashCode() {
int result = myPattern.hashCode();
result = 31 * result + (myCaseSensitive ? 1 : 0);
result = 31 * result + (myLowecaseTransform ? 1 : 0);
result = 31 * result + (myForwardDirection ? 1 : 0);
result = 31 * result + (myJavaIdentifier ? 1 : 0);
result = 31 * result + (myHandleEscapeSequences ? 1 : 0);
@@ -32,4 +32,29 @@ public class StringSearcherTest extends TestCase {
assertEquals(text.indexOf("bc"), index);
}
public void testCaseInsensitiveWithUnicode() {
String pattern = "SİL";
final String text = "SİL SIL";
final int firstPos = text.indexOf(pattern);
final int secondPos = text.indexOf("SIL");
StringSearcher searcher = new StringSearcher(pattern, false, true);
int index = searcher.scan(text);
assertEquals(firstPos, index);
assertEquals(secondPos, searcher.scan(text, index + 1, text.length()));
pattern = "sil";
searcher = new StringSearcher(pattern, false, true);
index = searcher.scan(text);
assertEquals(firstPos, index);
assertEquals(secondPos, searcher.scan(text, index + 1, text.length()));
searcher = new StringSearcher(pattern, false, false);
index = searcher.scan(text, 0, text.length());
assertEquals(secondPos, index);
assertEquals(firstPos, searcher.scan(text, 0, index - 1));
}
}