Recursively resolve @string/resource reference in key key spec parsing

Change-Id: I9d172605e90e828e00f7c4c8d49548498aa3b50d
main
Tadashi G. Takaoka 2012-02-03 19:34:47 +09:00
parent 9f491e34ac
commit aca8870128
3 changed files with 61 additions and 28 deletions

View File

@ -43,6 +43,8 @@ import java.util.Arrays;
public class KeySpecParser { public class KeySpecParser {
private static final boolean DEBUG = LatinImeLogger.sDBG; private static final boolean DEBUG = LatinImeLogger.sDBG;
private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
// Constants for parsing. // Constants for parsing.
private static int COMMA = ','; private static int COMMA = ',';
private static final char ESCAPE_CHAR = '\\'; private static final char ESCAPE_CHAR = '\\';
@ -274,13 +276,23 @@ public class KeySpecParser {
return resId; return resId;
} }
private static String resolveStringResource(String text, Resources res, int packageNameResId) { private static String resolveStringResource(String rawText, Resources res,
int packageNameResId) {
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 size = text.length(); final int size = text.length();
if (size < PREFIX_STRING.length()) { if (size < PREFIX_STRING.length()) {
return text; return text;
} }
StringBuilder sb = null; sb = null;
for (int pos = 0; pos < size; pos++) { for (int pos = 0; pos < size; pos++) {
final char c = text.charAt(pos); final char c = text.charAt(pos);
if (c == PREFIX_AT && text.startsWith(PREFIX_STRING, pos)) { if (c == PREFIX_AT && text.startsWith(PREFIX_STRING, pos)) {
@ -302,7 +314,13 @@ public class KeySpecParser {
sb.append(c); sb.append(c);
} }
} }
return (sb == null) ? text : sb.toString();
if (sb != null) {
text = sb.toString();
}
} while (sb != null);
return text;
} }
private static int searchResourceNameEnd(String text, int start) { private static int searchResourceNameEnd(String text, int start) {

View File

@ -50,4 +50,7 @@
<string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string> <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string>
<string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string> <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string>
<string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string> <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string>
<string name="indirect_string">@string/multiple_chars</string>
<string name="indirect_string_with_literal">x,@string/multiple_chars,y</string>
<string name="infinite_indirection">infinite,@string/infinite_indirection,loop</string>
</resources> </resources>

View File

@ -288,4 +288,16 @@ public class KeySpecParserCsvTests extends AndroidTestCase {
"abc@string/multiple_labels", "abc@string/multiple_labels",
"abcabc", "def", "ghi"); "abcabc", "def", "ghi");
} }
public void testParseIndirectReference() {
assertTextArray("Indirect",
"@string/indirect_string", "a", "b", "c");
assertTextArray("Indirect with literal",
"1,@string/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2");
}
public void testParseInfiniteIndirectReference() {
assertError("Infinite indirection",
"1,@string/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
}
} }