From b3fd70118119e736209173d34053974e61f936d8 Mon Sep 17 00:00:00 2001
From: "Tadashi G. Takaoka" <takaoka@google.com>
Date: Tue, 12 Feb 2013 16:00:28 +0900
Subject: [PATCH] Move parseCsvString to StringUtils

Change-Id: I602f33991ca57b6057ec2defe01573552b322857
---
 .../keyboard/internal/KeySpecParser.java      | 51 ++-----------------
 .../keyboard/internal/KeyStyle.java           |  5 +-
 .../android/inputmethod/latin/Constants.java  |  4 ++
 .../inputmethod/latin/SettingsValues.java     |  5 +-
 .../inputmethod/latin/StringUtils.java        | 38 ++++++++++++++
 .../internal/KeySpecParserCsvTests.java       |  4 +-
 6 files changed, 57 insertions(+), 50 deletions(-)

diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index 509068ac4a..b1813a141b 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -53,8 +53,6 @@ public final class KeySpecParser {
     private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
 
     // Constants for parsing.
-    private static int COMMA = ',';
-    private static final char ESCAPE_CHAR = '\\';
     private static final char LABEL_END = '|';
     private static final String PREFIX_TEXT = "!text/";
     static final String PREFIX_ICON = "!icon/";
@@ -80,14 +78,14 @@ public final class KeySpecParser {
     }
 
     private static String parseEscape(final String text) {
-        if (text.indexOf(ESCAPE_CHAR) < 0) {
+        if (text.indexOf(Constants.CSV_ESCAPE) < 0) {
             return text;
         }
         final int length = text.length();
         final StringBuilder sb = new StringBuilder();
         for (int pos = 0; pos < length; pos++) {
             final char c = text.charAt(pos);
-            if (c == ESCAPE_CHAR && pos + 1 < length) {
+            if (c == Constants.CSV_ESCAPE && pos + 1 < length) {
                 // Skip escape char
                 pos++;
                 sb.append(text.charAt(pos));
@@ -99,7 +97,7 @@ public final class KeySpecParser {
     }
 
     private static int indexOfLabelEnd(final String moreKeySpec, final int start) {
-        if (moreKeySpec.indexOf(ESCAPE_CHAR, start) < 0) {
+        if (moreKeySpec.indexOf(Constants.CSV_ESCAPE, start) < 0) {
             final int end = moreKeySpec.indexOf(LABEL_END, start);
             if (end == 0) {
                 throw new KeySpecParserError(LABEL_END + " at " + start + ": " + moreKeySpec);
@@ -109,7 +107,7 @@ public final class KeySpecParser {
         final int length = moreKeySpec.length();
         for (int pos = start; pos < length; pos++) {
             final char c = moreKeySpec.charAt(pos);
-            if (c == ESCAPE_CHAR && pos + 1 < length) {
+            if (c == Constants.CSV_ESCAPE && pos + 1 < length) {
                 // Skip escape char
                 pos++;
             } else if (c == LABEL_END) {
@@ -353,7 +351,7 @@ public final class KeySpecParser {
                     final String name = text.substring(pos + prefixLen, end);
                     sb.append(textsSet.getText(name));
                     pos = end - 1;
-                } else if (c == ESCAPE_CHAR) {
+                } else if (c == Constants.CSV_ESCAPE) {
                     if (sb != null) {
                         // Append both escape character and escaped character.
                         sb.append(text.substring(pos, Math.min(pos + 2, size)));
@@ -385,45 +383,6 @@ public final class KeySpecParser {
         return size;
     }
 
-    public static String[] parseCsvString(final String rawText, final KeyboardTextsSet textsSet) {
-        final String text = resolveTextReference(rawText, textsSet);
-        final int size = text.length();
-        if (size == 0) {
-            return null;
-        }
-        if (StringUtils.codePointCount(text) == 1) {
-            return text.codePointAt(0) == COMMA ? null : new String[] { text };
-        }
-
-        ArrayList<String> list = null;
-        int start = 0;
-        for (int pos = 0; pos < size; pos++) {
-            final char c = text.charAt(pos);
-            if (c == COMMA) {
-                // Skip empty entry.
-                if (pos - start > 0) {
-                    if (list == null) {
-                        list = CollectionUtils.newArrayList();
-                    }
-                    list.add(text.substring(start, pos));
-                }
-                // Skip comma
-                start = pos + 1;
-            } else if (c == ESCAPE_CHAR) {
-                // Skip escape character and escaped character.
-                pos++;
-            }
-        }
-        final String remain = (size - start > 0) ? text.substring(start) : null;
-        if (list == null) {
-            return remain != null ? new String[] { remain } : null;
-        }
-        if (remain != null) {
-            list.add(remain);
-        }
-        return list.toArray(new String[list.size()]);
-    }
-
     public static int getIntValue(final String[] moreKeys, final String key,
             final int defaultValue) {
         if (moreKeys == null) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
index fe75e20aef..5db3ebbd17 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
@@ -18,6 +18,8 @@ package com.android.inputmethod.keyboard.internal;
 
 import android.content.res.TypedArray;
 
+import com.android.inputmethod.latin.StringUtils;
+
 public abstract class KeyStyle {
     private final KeyboardTextsSet mTextsSet;
 
@@ -39,7 +41,8 @@ public abstract class KeyStyle {
 
     protected String[] parseStringArray(final TypedArray a, final int index) {
         if (a.hasValue(index)) {
-            return KeySpecParser.parseCsvString(a.getString(index), mTextsSet);
+            final String text = KeySpecParser.resolveTextReference(a.getString(index), mTextsSet);
+            return StringUtils.parseCsvString(text);
         }
         return null;
     }
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 85cc552326..422448edf4 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -215,6 +215,10 @@ public final class Constants {
         }
     }
 
+    // Constants for CSV parsing.
+    public static final char CSV_SEPARATOR = ',';
+    public static final char CSV_ESCAPE = '\\';
+
     private Constants() {
         // This utility class is not publicly instantiable.
     }
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 728f6b2812..d058680293 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -89,8 +89,8 @@ public final class SettingsValues {
         mWordConnectors =
                 StringUtils.toCodePointArray(res.getString(R.string.symbols_word_connectors));
         Arrays.sort(mWordConnectors);
-        final String[] suggestPuncsSpec = KeySpecParser.parseCsvString(
-                res.getString(R.string.suggested_punctuations), null);
+        final String[] suggestPuncsSpec = StringUtils.parseCsvString(res.getString(
+                R.string.suggested_punctuations));
         mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
         mWordSeparators = res.getString(R.string.symbols_word_separators);
         mHintToSaveText = res.getText(R.string.hint_add_to_dictionary);
@@ -211,6 +211,7 @@ public final class SettingsValues {
         final ArrayList<SuggestedWordInfo> puncList = CollectionUtils.newArrayList();
         if (puncs != null) {
             for (final String puncSpec : puncs) {
+                // TODO: Stop using KeySpceParser.getLabel().
                 puncList.add(new SuggestedWordInfo(KeySpecParser.getLabel(puncSpec),
                         SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED,
                         Dictionary.TYPE_HARDCODED));
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index d00edbe92b..6fac0d2d34 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -372,4 +372,42 @@ public final class StringUtils {
         // Here we arrived at the start of the line. This should behave exactly like whitespace.
         return (START == state || LETTER == state) ? noCaps : caps;
     }
+
+    public static String[] parseCsvString(final String text) {
+        final int size = text.length();
+        if (size == 0) {
+            return null;
+        }
+        if (codePointCount(text) == 1) {
+            return text.codePointAt(0) == Constants.CSV_SEPARATOR ? null : new String[] { text };
+        }
+
+        ArrayList<String> list = null;
+        int start = 0;
+        for (int pos = 0; pos < size; pos++) {
+            final char c = text.charAt(pos);
+            if (c == Constants.CSV_SEPARATOR) {
+                // Skip empty entry.
+                if (pos - start > 0) {
+                    if (list == null) {
+                        list = CollectionUtils.newArrayList();
+                    }
+                    list.add(text.substring(start, pos));
+                }
+                // Skip comma
+                start = pos + 1;
+            } else if (c == Constants.CSV_ESCAPE) {
+                // Skip escape character and escaped character.
+                pos++;
+            }
+        }
+        final String remain = (size - start > 0) ? text.substring(start) : null;
+        if (list == null) {
+            return remain != null ? new String[] { remain } : null;
+        }
+        if (remain != null) {
+            list.add(remain);
+        }
+        return list.toArray(new String[list.size()]);
+    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java
index cee62ca384..d58e1627fc 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java
@@ -21,6 +21,7 @@ import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.latin.CollectionUtils;
+import com.android.inputmethod.latin.StringUtils;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -74,7 +75,8 @@ public class KeySpecParserCsvTests extends InstrumentationTestCase {
     }
 
     private void assertTextArray(String message, String value, String ... expectedArray) {
-        final String[] actual = KeySpecParser.parseCsvString(value, mTextsSet);
+        final String resolvedActual = KeySpecParser.resolveTextReference(value, mTextsSet);
+        final String[] actual = StringUtils.parseCsvString(resolvedActual);
         final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
         assertArrayEquals(message, expected, actual);
     }
-- 
GitLab