[CB25] Refactor some array copying
Bug: 13406701 Change-Id: I09edd822f5cc2446b324d41c76d835bcff1191e6main
parent
27a4f2e5e1
commit
5f430e0189
|
@ -247,7 +247,9 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
final String prevWord, final ProximityInfo proximityInfo,
|
final String prevWord, final ProximityInfo proximityInfo,
|
||||||
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
|
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
|
||||||
final int sessionId, final float[] inOutLanguageWeight) {
|
final int sessionId, final float[] inOutLanguageWeight) {
|
||||||
if (!isValidDictionary()) return null;
|
if (!isValidDictionary()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE);
|
Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE);
|
||||||
// TODO: toLowerCase in the native code
|
// TODO: toLowerCase in the native code
|
||||||
|
@ -257,12 +259,11 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
final boolean isGesture = composer.isBatchMode();
|
final boolean isGesture = composer.isBatchMode();
|
||||||
final int inputSize;
|
final int inputSize;
|
||||||
if (!isGesture) {
|
if (!isGesture) {
|
||||||
final int composerSize = composer.sizeWithoutTrailingSingleQuotes();
|
inputSize = composer.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
|
||||||
if (composerSize > MAX_WORD_LENGTH - 1) return null;
|
mInputCodePoints, MAX_WORD_LENGTH);
|
||||||
for (int i = 0; i < composerSize; i++) {
|
if (inputSize < 0) {
|
||||||
mInputCodePoints[i] = composer.getCodeAt(i);
|
return null;
|
||||||
}
|
}
|
||||||
inputSize = composerSize;
|
|
||||||
} else {
|
} else {
|
||||||
inputSize = inputPointers.getPointerSize();
|
inputSize = inputPointers.getPointerSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,29 +131,42 @@ public final class WordComposer {
|
||||||
return mCodePointSize;
|
return mCodePointSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the code points in the typed word to a destination array of ints.
|
||||||
|
*
|
||||||
|
* If the array is too small to hold the code points in the typed word, nothing is copied and
|
||||||
|
* -1 is returned.
|
||||||
|
*
|
||||||
|
* @param destination the array of ints.
|
||||||
|
* @param maxSize the size of the array.
|
||||||
|
* @return the number of copied code points.
|
||||||
|
*/
|
||||||
|
public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
|
||||||
|
final int[] destination, final int maxSize) {
|
||||||
|
int i = mTypedWordCache.length() - 1;
|
||||||
|
while (i >= 0 && mTypedWordCache.charAt(i) == Constants.CODE_SINGLE_QUOTE) {
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
if (i < 0) {
|
||||||
|
// The string is empty or contains only single quotes.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
final int codePointSize = Character.codePointCount(mTypedWordCache, 0, i);
|
||||||
|
if (codePointSize > maxSize) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return StringUtils.copyCodePointsAndReturnCodePointCount(destination, mTypedWordCache, 0,
|
||||||
|
i + 1, true /* downCase */);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSingleLetter() {
|
public boolean isSingleLetter() {
|
||||||
return size() == 1;
|
return size() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the composition contains trailing quotes, we don't pass them to the suggestion engine.
|
|
||||||
// This is because "'tgis'" should be corrected to "'this'", but we can't afford to consider
|
|
||||||
// single quotes as separators because of their very common use as apostrophes.
|
|
||||||
public int sizeWithoutTrailingSingleQuotes() {
|
|
||||||
return size() - mTrailingSingleQuotesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isComposingWord() {
|
public final boolean isComposingWord() {
|
||||||
return size() > 0;
|
return size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make sure that the index should not exceed MAX_WORD_LENGTH
|
|
||||||
public int getCodeAt(int index) {
|
|
||||||
if (index >= MAX_WORD_LENGTH) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return mPrimaryKeyCodes[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputPointers getInputPointers() {
|
public InputPointers getInputPointers() {
|
||||||
return mInputPointers;
|
return mInputPointers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,13 +191,42 @@ public final class StringUtils {
|
||||||
}
|
}
|
||||||
final int[] codePoints =
|
final int[] codePoints =
|
||||||
new int[Character.codePointCount(charSequence, startIndex, endIndex)];
|
new int[Character.codePointCount(charSequence, startIndex, endIndex)];
|
||||||
|
copyCodePointsAndReturnCodePointCount(codePoints, charSequence, startIndex, endIndex,
|
||||||
|
false /* downCase */);
|
||||||
|
return codePoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the codepoints in a CharSequence to an int array.
|
||||||
|
*
|
||||||
|
* This method assumes there is enough space in the array to store the code points. The size
|
||||||
|
* can be measured with Character#codePointCount(CharSequence, int, int) before passing to this
|
||||||
|
* method. If the int array is too small, an ArrayIndexOutOfBoundsException will be thrown.
|
||||||
|
* Also, this method makes no effort to be thread-safe. Do not modify the CharSequence while
|
||||||
|
* this method is running, or the behavior is undefined.
|
||||||
|
* This method can optionally downcase code points before copying them, but it pays no attention
|
||||||
|
* to locale while doing so.
|
||||||
|
*
|
||||||
|
* @param destination the int array.
|
||||||
|
* @param charSequence the CharSequence.
|
||||||
|
* @param startIndex the start index inside the string in java chars, inclusive.
|
||||||
|
* @param endIndex the end index inside the string in java chars, exclusive.
|
||||||
|
* @param downCase if this is true, code points will be downcased before being copied.
|
||||||
|
* @return the number of copied code points.
|
||||||
|
*/
|
||||||
|
public static int copyCodePointsAndReturnCodePointCount(final int[] destination,
|
||||||
|
final CharSequence charSequence, final int startIndex, final int endIndex,
|
||||||
|
final boolean downCase) {
|
||||||
int destIndex = 0;
|
int destIndex = 0;
|
||||||
for (int index = startIndex; index < endIndex;
|
for (int index = startIndex; index < endIndex;
|
||||||
index = Character.offsetByCodePoints(charSequence, index, 1)) {
|
index = Character.offsetByCodePoints(charSequence, index, 1)) {
|
||||||
codePoints[destIndex] = Character.codePointAt(charSequence, index);
|
final int codePoint = Character.codePointAt(charSequence, index);
|
||||||
|
// TODO: stop using this, as it's not aware of the locale and does not always do
|
||||||
|
// the right thing.
|
||||||
|
destination[destIndex] = downCase ? Character.toLowerCase(codePoint) : codePoint;
|
||||||
destIndex++;
|
destIndex++;
|
||||||
}
|
}
|
||||||
return codePoints;
|
return destIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int[] toSortedCodePointArray(final String string) {
|
public static int[] toSortedCodePointArray(final String string) {
|
||||||
|
|
|
@ -308,4 +308,68 @@ public class StringAndJsonUtilsTests extends AndroidTestCase {
|
||||||
assertEquals(objs[i], newObjArray.get(i));
|
assertEquals(objs[i], newObjArray.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testToCodePointArray() {
|
||||||
|
final String STR_WITH_SUPPLEMENTARY_CHAR = "abcde\uD861\uDED7fgh\u0000\u2002\u2003\u3000xx";
|
||||||
|
final int[] EXPECTED_RESULT = new int[] { 'a', 'b', 'c', 'd', 'e', 0x286D7, 'f', 'g', 'h',
|
||||||
|
0, 0x2002, 0x2003, 0x3000, 'x', 'x'};
|
||||||
|
final int[] codePointArray = StringUtils.toCodePointArray(STR_WITH_SUPPLEMENTARY_CHAR, 0,
|
||||||
|
STR_WITH_SUPPLEMENTARY_CHAR.length());
|
||||||
|
assertEquals("toCodePointArray, size matches", codePointArray.length,
|
||||||
|
EXPECTED_RESULT.length);
|
||||||
|
for (int i = 0; i < EXPECTED_RESULT.length; ++i) {
|
||||||
|
assertEquals("toCodePointArray position " + i, codePointArray[i], EXPECTED_RESULT[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCopyCodePointsAndReturnCodePointCount() {
|
||||||
|
final String STR_WITH_SUPPLEMENTARY_CHAR = "AbcDE\uD861\uDED7fGh\u0000\u2002\u3000あx";
|
||||||
|
final int[] EXPECTED_RESULT = new int[] { 'A', 'b', 'c', 'D', 'E', 0x286D7,
|
||||||
|
'f', 'G', 'h', 0, 0x2002, 0x3000, 'あ', 'x'};
|
||||||
|
final int[] EXPECTED_RESULT_DOWNCASE = new int[] { 'a', 'b', 'c', 'd', 'e', 0x286D7,
|
||||||
|
'f', 'g', 'h', 0, 0x2002, 0x3000, 'あ', 'x'};
|
||||||
|
|
||||||
|
int[] codePointArray = new int[50];
|
||||||
|
int codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
|
||||||
|
STR_WITH_SUPPLEMENTARY_CHAR, 0,
|
||||||
|
STR_WITH_SUPPLEMENTARY_CHAR.length(), false /* downCase */);
|
||||||
|
assertEquals("copyCodePointsAndReturnCodePointCount, size matches", codePointCount,
|
||||||
|
EXPECTED_RESULT.length);
|
||||||
|
for (int i = 0; i < codePointCount; ++i) {
|
||||||
|
assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
|
||||||
|
EXPECTED_RESULT[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
|
||||||
|
STR_WITH_SUPPLEMENTARY_CHAR, 0,
|
||||||
|
STR_WITH_SUPPLEMENTARY_CHAR.length(), true /* downCase */);
|
||||||
|
assertEquals("copyCodePointsAndReturnCodePointCount downcase, size matches", codePointCount,
|
||||||
|
EXPECTED_RESULT_DOWNCASE.length);
|
||||||
|
for (int i = 0; i < codePointCount; ++i) {
|
||||||
|
assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
|
||||||
|
EXPECTED_RESULT_DOWNCASE[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int JAVA_CHAR_COUNT = 8;
|
||||||
|
final int CODEPOINT_COUNT = 7;
|
||||||
|
codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
|
||||||
|
STR_WITH_SUPPLEMENTARY_CHAR, 0, JAVA_CHAR_COUNT, false /* downCase */);
|
||||||
|
assertEquals("copyCodePointsAndReturnCodePointCount, size matches", codePointCount,
|
||||||
|
CODEPOINT_COUNT);
|
||||||
|
for (int i = 0; i < codePointCount; ++i) {
|
||||||
|
assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
|
||||||
|
EXPECTED_RESULT[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean exceptionHappened = false;
|
||||||
|
codePointArray = new int[5];
|
||||||
|
try {
|
||||||
|
codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
|
||||||
|
STR_WITH_SUPPLEMENTARY_CHAR, 0, JAVA_CHAR_COUNT, false /* downCase */);
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
exceptionHappened = true;
|
||||||
|
}
|
||||||
|
assertTrue("copyCodePointsAndReturnCodePointCount throws when array is too small",
|
||||||
|
exceptionHappened);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue