Refactor KeyboardTextsSet class
Change-Id: I0b48c85aa2c291e1e7ee25d61c558700fc677e29
This commit is contained in:
parent
d245f6c9e2
commit
0bae2ab460
6 changed files with 138 additions and 73 deletions
|
@ -48,13 +48,10 @@ import java.util.Arrays;
|
|||
public final class KeySpecParser {
|
||||
private static final boolean DEBUG = LatinImeLogger.sDBG;
|
||||
|
||||
private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
|
||||
|
||||
// Constants for parsing.
|
||||
private static final char COMMA = ',';
|
||||
private static final char BACKSLASH = '\\';
|
||||
private static final char VERTICAL_BAR = '|';
|
||||
private static final String PREFIX_TEXT = "!text/";
|
||||
static final String PREFIX_ICON = "!icon/";
|
||||
private static final String PREFIX_CODE = "!code/";
|
||||
private static final String PREFIX_HEX = "0x";
|
||||
|
@ -361,68 +358,6 @@ public final class KeySpecParser {
|
|||
}
|
||||
}
|
||||
|
||||
public static String resolveTextReference(final String rawText,
|
||||
final KeyboardTextsSet textsSet) {
|
||||
if (TextUtils.isEmpty(rawText)) {
|
||||
return null;
|
||||
}
|
||||
int level = 0;
|
||||
String text = rawText;
|
||||
StringBuilder sb;
|
||||
do {
|
||||
level++;
|
||||
if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
|
||||
throw new RuntimeException("too many @string/resource indirection: " + text);
|
||||
}
|
||||
|
||||
final int prefixLen = PREFIX_TEXT.length();
|
||||
final int size = text.length();
|
||||
if (size < prefixLen) {
|
||||
return TextUtils.isEmpty(text) ? null : text;
|
||||
}
|
||||
|
||||
sb = null;
|
||||
for (int pos = 0; pos < size; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
if (text.startsWith(PREFIX_TEXT, pos) && textsSet != null) {
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder(text.substring(0, pos));
|
||||
}
|
||||
final int end = searchTextNameEnd(text, pos + prefixLen);
|
||||
final String name = text.substring(pos + prefixLen, end);
|
||||
sb.append(textsSet.getText(name));
|
||||
pos = end - 1;
|
||||
} else if (c == BACKSLASH) {
|
||||
if (sb != null) {
|
||||
// Append both escape character and escaped character.
|
||||
sb.append(text.substring(pos, Math.min(pos + 2, size)));
|
||||
}
|
||||
pos++;
|
||||
} else if (sb != null) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (sb != null) {
|
||||
text = sb.toString();
|
||||
}
|
||||
} while (sb != null);
|
||||
return TextUtils.isEmpty(text) ? null : text;
|
||||
}
|
||||
|
||||
private static int searchTextNameEnd(final String text, final int start) {
|
||||
final int size = text.length();
|
||||
for (int pos = start; pos < size; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
// Label name should be consisted of [a-zA-Z_0-9].
|
||||
if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
|
||||
continue;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public static int getIntValue(final String[] moreKeys, final String key,
|
||||
final int defaultValue) {
|
||||
if (moreKeys == null) {
|
||||
|
|
|
@ -32,14 +32,14 @@ public abstract class KeyStyle {
|
|||
|
||||
protected String parseString(final TypedArray a, final int index) {
|
||||
if (a.hasValue(index)) {
|
||||
return KeySpecParser.resolveTextReference(a.getString(index), mTextsSet);
|
||||
return mTextsSet.resolveTextReference(a.getString(index));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String[] parseStringArray(final TypedArray a, final int index) {
|
||||
if (a.hasValue(index)) {
|
||||
final String text = KeySpecParser.resolveTextReference(a.getString(index), mTextsSet);
|
||||
final String text = mTextsSet.resolveTextReference(a.getString(index));
|
||||
return KeySpecParser.splitKeySpecs(text);
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard.internal;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||
|
@ -45,6 +46,10 @@ import java.util.HashMap;
|
|||
* KeyboardTextsSet.java
|
||||
*/
|
||||
public final class KeyboardTextsSet {
|
||||
private static final String PREFIX_TEXT = "!text/";
|
||||
private static final char BACKSLASH = '\\';
|
||||
private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
|
||||
|
||||
// Language to texts map.
|
||||
private static final HashMap<String, String[]> sLocaleToTextsMap = CollectionUtils.newHashMap();
|
||||
private static final HashMap<String, Integer> sNameToIdsMap = CollectionUtils.newHashMap();
|
||||
|
@ -87,6 +92,67 @@ public final class KeyboardTextsSet {
|
|||
return (text == null) ? LANGUAGE_DEFAULT[id] : text;
|
||||
}
|
||||
|
||||
private static int searchTextNameEnd(final String text, final int start) {
|
||||
final int size = text.length();
|
||||
for (int pos = start; pos < size; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
// Label name should be consisted of [a-zA-Z_0-9].
|
||||
if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
|
||||
continue;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public String resolveTextReference(final String rawText) {
|
||||
if (TextUtils.isEmpty(rawText)) {
|
||||
return null;
|
||||
}
|
||||
int level = 0;
|
||||
String text = rawText;
|
||||
StringBuilder sb;
|
||||
do {
|
||||
level++;
|
||||
if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
|
||||
throw new RuntimeException("too many @string/resource indirection: " + text);
|
||||
}
|
||||
|
||||
final int prefixLen = PREFIX_TEXT.length();
|
||||
final int size = text.length();
|
||||
if (size < prefixLen) {
|
||||
return TextUtils.isEmpty(text) ? null : text;
|
||||
}
|
||||
|
||||
sb = null;
|
||||
for (int pos = 0; pos < size; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
if (text.startsWith(PREFIX_TEXT, pos)) {
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder(text.substring(0, pos));
|
||||
}
|
||||
final int end = searchTextNameEnd(text, pos + prefixLen);
|
||||
final String name = text.substring(pos + prefixLen, end);
|
||||
sb.append(getText(name));
|
||||
pos = end - 1;
|
||||
} else if (c == BACKSLASH) {
|
||||
if (sb != null) {
|
||||
// Append both escape character and escaped character.
|
||||
sb.append(text.substring(pos, Math.min(pos + 2, size)));
|
||||
}
|
||||
pos++;
|
||||
} else if (sb != null) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (sb != null) {
|
||||
text = sb.toString();
|
||||
}
|
||||
} while (sb != null);
|
||||
return TextUtils.isEmpty(text) ? null : text;
|
||||
}
|
||||
|
||||
// These texts' name should be aligned with the @string/<name> in
|
||||
// values*/strings-action-keys.xml.
|
||||
private static final String[] RESOURCE_NAMES = {
|
||||
|
|
|
@ -92,7 +92,7 @@ public class KeySpecParserSplitTests extends InstrumentationTestCase {
|
|||
|
||||
private void assertTextArray(final String message, final String value,
|
||||
final String ... expectedArray) {
|
||||
final String resolvedActual = KeySpecParser.resolveTextReference(value, mTextsSet);
|
||||
final String resolvedActual = mTextsSet.resolveTextReference(value);
|
||||
final String[] actual = KeySpecParser.splitKeySpecs(resolvedActual);
|
||||
final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
|
||||
assertArrayEquals(message, expected, actual);
|
||||
|
@ -117,13 +117,11 @@ public class KeySpecParserSplitTests extends InstrumentationTestCase {
|
|||
private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3;
|
||||
|
||||
public void testResolveNullText() {
|
||||
assertNull("resolve null", KeySpecParser.resolveTextReference(
|
||||
null, mTextsSet));
|
||||
assertNull("resolve null", mTextsSet.resolveTextReference(null));
|
||||
}
|
||||
|
||||
public void testResolveEmptyText() {
|
||||
assertNull("resolve empty text", KeySpecParser.resolveTextReference(
|
||||
"!text/empty_string", mTextsSet));
|
||||
assertNull("resolve empty text", mTextsSet.resolveTextReference("!text/empty_string"));
|
||||
}
|
||||
|
||||
public void testSplitZero() {
|
||||
|
|
|
@ -73,7 +73,7 @@ public class KeySpecParserTests extends AndroidTestCase {
|
|||
|
||||
private void assertParser(String message, String moreKeySpec, String expectedLabel,
|
||||
String expectedOutputText, int expectedIcon, int expectedCode) {
|
||||
final String labelResolved = KeySpecParser.resolveTextReference(moreKeySpec, mTextsSet);
|
||||
final String labelResolved = mTextsSet.resolveTextReference(moreKeySpec);
|
||||
final MoreKeySpec spec = new MoreKeySpec(labelResolved, false /* needsToUpperCase */,
|
||||
Locale.US, mCodesSet);
|
||||
assertEquals(message + " [label]", expectedLabel, spec.mLabel);
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard.internal;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||
|
@ -45,6 +46,10 @@ import java.util.HashMap;
|
|||
* KeyboardTextsSet.java
|
||||
*/
|
||||
public final class KeyboardTextsSet {
|
||||
private static final String PREFIX_TEXT = "!text/";
|
||||
private static final char BACKSLASH = '\\';
|
||||
private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
|
||||
|
||||
// Language to texts map.
|
||||
private static final HashMap<String, String[]> sLocaleToTextsMap = CollectionUtils.newHashMap();
|
||||
private static final HashMap<String, Integer> sNameToIdsMap = CollectionUtils.newHashMap();
|
||||
|
@ -87,6 +92,67 @@ public final class KeyboardTextsSet {
|
|||
return (text == null) ? LANGUAGE_DEFAULT[id] : text;
|
||||
}
|
||||
|
||||
private static int searchTextNameEnd(final String text, final int start) {
|
||||
final int size = text.length();
|
||||
for (int pos = start; pos < size; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
// Label name should be consisted of [a-zA-Z_0-9].
|
||||
if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
|
||||
continue;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public String resolveTextReference(final String rawText) {
|
||||
if (TextUtils.isEmpty(rawText)) {
|
||||
return null;
|
||||
}
|
||||
int level = 0;
|
||||
String text = rawText;
|
||||
StringBuilder sb;
|
||||
do {
|
||||
level++;
|
||||
if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
|
||||
throw new RuntimeException("too many @string/resource indirection: " + text);
|
||||
}
|
||||
|
||||
final int prefixLen = PREFIX_TEXT.length();
|
||||
final int size = text.length();
|
||||
if (size < prefixLen) {
|
||||
return TextUtils.isEmpty(text) ? null : text;
|
||||
}
|
||||
|
||||
sb = null;
|
||||
for (int pos = 0; pos < size; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
if (text.startsWith(PREFIX_TEXT, pos)) {
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder(text.substring(0, pos));
|
||||
}
|
||||
final int end = searchTextNameEnd(text, pos + prefixLen);
|
||||
final String name = text.substring(pos + prefixLen, end);
|
||||
sb.append(getText(name));
|
||||
pos = end - 1;
|
||||
} else if (c == BACKSLASH) {
|
||||
if (sb != null) {
|
||||
// Append both escape character and escaped character.
|
||||
sb.append(text.substring(pos, Math.min(pos + 2, size)));
|
||||
}
|
||||
pos++;
|
||||
} else if (sb != null) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (sb != null) {
|
||||
text = sb.toString();
|
||||
}
|
||||
} while (sb != null);
|
||||
return TextUtils.isEmpty(text) ? null : text;
|
||||
}
|
||||
|
||||
// These texts' name should be aligned with the @string/<name> in
|
||||
// values*/strings-action-keys.xml.
|
||||
private static final String[] RESOURCE_NAMES = {
|
||||
|
|
Loading…
Reference in a new issue