diff options
author | 2012-07-04 15:38:14 +0900 | |
---|---|---|
committer | 2012-07-04 15:38:21 +0900 | |
commit | c68b37964b083015967ce290991ad69d29a4055d (patch) | |
tree | 909bddc0f0c699b6344015e7ff67e31c0a1f4eff /java/src/com/android/inputmethod/latin/StringUtils.java | |
parent | 1e094ac19b99c47f0b8a5108e20949ac91cfa03e (diff) | |
parent | 30a324a58dbe1e2dc47d83c1bcc0af262ab0d542 (diff) | |
download | latinime-c68b37964b083015967ce290991ad69d29a4055d.tar.gz latinime-c68b37964b083015967ce290991ad69d29a4055d.tar.xz latinime-c68b37964b083015967ce290991ad69d29a4055d.zip |
Merge remote-tracking branch 'goog/master' into mergescript
Conflicts:
CleanSpec.mk
java/Android.mk
java/res/drawable-large-hdpi/btn_keyboard_key_popup_selected_holo.9.png
java/res/drawable-large-hdpi/hint_popup_holo.9.png
java/res/drawable-large-hdpi/sym_keyboard_numsymbol_holo.png
java/res/drawable-large-hdpi/sym_keyboard_tab_holo.png
java/res/drawable-large-land-hdpi/hint_popup_holo.9.png
java/res/drawable-large-land-mdpi/hint_popup_holo.9.png
java/res/drawable-large-land-xhdpi/hint_popup_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_light_normal_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_light_pressed_holo.9.png
java/res/drawable-large-mdpi/btn_keyboard_key_popup_selected_holo.9.png
java/res/drawable-large-mdpi/hint_popup_holo.9.png
java/res/drawable-large-mdpi/keyboard_background_holo.9.png
java/res/drawable-large-mdpi/keyboard_popup_panel_background_holo.9.png
java/res/drawable-large-mdpi/keyboard_suggest_strip_holo.9.png
java/res/drawable-large-mdpi/sym_keyboard_delete_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num0_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num1_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num2_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num3_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num4_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num5_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num6_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num7_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num8_holo.png
java/res/drawable-large-mdpi/sym_keyboard_num9_holo.png
java/res/drawable-large-mdpi/sym_keyboard_numbpound_holo.png
java/res/drawable-large-mdpi/sym_keyboard_numbstar_holo.png
java/res/drawable-large-mdpi/sym_keyboard_numsymbol_holo.png
java/res/drawable-large-mdpi/sym_keyboard_return_holo.png
java/res/drawable-large-mdpi/sym_keyboard_settings_holo.png
java/res/drawable-large-mdpi/sym_keyboard_shift_holo.png
java/res/drawable-large-mdpi/sym_keyboard_shift_locked_holo.png
java/res/drawable-large-mdpi/sym_keyboard_space_holo.png
java/res/drawable-large-mdpi/sym_keyboard_tab_holo.png
java/res/drawable-large-mdpi/sym_keyboard_voice_holo.png
java/res/drawable-large-mdpi/sym_keyboard_voice_off_holo.png
java/res/drawable-large-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
java/res/drawable-large-xhdpi/hint_popup_holo.9.png
java/res/drawable-large-xhdpi/sym_keyboard_numsymbol_holo.png
java/res/drawable-large-xhdpi/sym_keyboard_tab_holo.png
java/res/drawable-xlarge-hdpi/btn_keyboard_key_popup_selected_holo.9.png
java/res/drawable-xlarge-hdpi/hint_popup_holo.9.png
java/res/drawable-xlarge-land-hdpi/hint_popup_holo.9.png
java/res/drawable-xlarge-land-mdpi/hint_popup_holo.9.png
java/res/drawable-xlarge-land-xhdpi/hint_popup_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_normal_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_light_pressed_holo.9.png
java/res/drawable-xlarge-mdpi/btn_keyboard_key_popup_selected_holo.9.png
java/res/drawable-xlarge-mdpi/hint_popup_holo.9.png
java/res/drawable-xlarge-mdpi/keyboard_background_holo.9.png
java/res/drawable-xlarge-mdpi/keyboard_popup_panel_background_holo.9.png
java/res/drawable-xlarge-mdpi/keyboard_suggest_strip_holo.9.png
java/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num0_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num1_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num2_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num3_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num4_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num5_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num6_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num7_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num8_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_num9_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_numbpound_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_numbstar_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_return_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_settings_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_shift_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_space_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_voice_holo.png
java/res/drawable-xlarge-mdpi/sym_keyboard_voice_off_holo.png
java/res/drawable-xlarge-xhdpi/btn_keyboard_key_popup_selected_holo.9.png
java/res/drawable-xlarge-xhdpi/hint_popup_holo.9.png
java/res/layout-xlarge/recognition_status.xml
java/res/values-af/strings.xml
java/res/values-am/strings.xml
java/res/values-ar/strings.xml
java/res/values-be/strings.xml
java/res/values-bg/strings.xml
java/res/values-ca/strings.xml
java/res/values-cs/strings.xml
java/res/values-da/strings.xml
java/res/values-de/strings.xml
java/res/values-el/strings.xml
java/res/values-en-rGB/strings.xml
java/res/values-es-rUS/strings.xml
java/res/values-es/strings.xml
java/res/values-et/strings.xml
java/res/values-fa/strings.xml
java/res/values-fi/strings.xml
java/res/values-fr/strings.xml
java/res/values-hi/strings.xml
java/res/values-hr/strings.xml
java/res/values-hu/strings.xml
java/res/values-in/strings.xml
java/res/values-it/strings.xml
java/res/values-iw/strings.xml
java/res/values-ja/strings.xml
java/res/values-ko/strings.xml
java/res/values-large/donottranslate.xml
java/res/values-lt/strings.xml
java/res/values-lv/strings.xml
java/res/values-ms/strings.xml
java/res/values-nb/strings.xml
java/res/values-nl/strings.xml
java/res/values-pl/strings.xml
java/res/values-pt-rPT/strings.xml
java/res/values-pt/strings.xml
java/res/values-rm/strings.xml
java/res/values-ro/strings.xml
java/res/values-ru/strings.xml
java/res/values-sk/strings.xml
java/res/values-sl/strings.xml
java/res/values-sr/strings.xml
java/res/values-sv/strings.xml
java/res/values-sw/strings.xml
java/res/values-sw600dp/donottranslate.xml
java/res/values-sw768dp/donottranslate.xml
java/res/values-th/strings.xml
java/res/values-tl/strings.xml
java/res/values-tr/strings.xml
java/res/values-uk/strings.xml
java/res/values-vi/strings.xml
java/res/values-xlarge/donottranslate.xml
java/res/values-zh-rCN/strings.xml
java/res/values-zh-rTW/strings.xml
java/res/values-zu/strings.xml
java/res/values/keypress-vibration-durations.xml
java/res/values/predefined-subtypes.xml
java/res/xml-large-land/kbd_popup_template.xml
java/res/xml-large/kbd_key_styles.xml
java/res/xml-large/kbd_popup_template.xml
java/res/xml-large/kbd_qwerty_f2.xml
java/res/xml-large/kbd_qwerty_row1.xml
java/res/xml-large/kbd_qwerty_row2.xml
java/res/xml-large/kbd_qwerty_row3.xml
java/res/xml-large/kbd_qwerty_row4.xml
java/res/xml-large/kbd_row3_right.xml
java/res/xml-large/kbd_rows_arabic.xml
java/res/xml-large/kbd_rows_azerty.xml
java/res/xml-large/kbd_rows_hebrew.xml
java/res/xml-large/kbd_rows_qwerty.xml
java/res/xml-large/kbd_rows_qwertz.xml
java/res/xml-large/kbd_rows_russian.xml
java/res/xml-large/kbd_rows_scandinavian.xml
java/res/xml-large/kbd_rows_serbian.xml
java/res/xml-large/kbd_rows_spanish.xml
java/res/xml-large/kbd_symbols.xml
java/res/xml-large/kbd_symbols_shift.xml
java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml
java/res/xml-sw600dp-land/kbd_popup_template.xml
java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml
java/res/xml-sw600dp/kbd_popup_template.xml
java/res/xml-sw600dp/kbd_row3_right.xml
java/res/xml-sw600dp/kbd_rows_qwerty.xml
java/res/xml-sw600dp/keys_comma_period.xml
java/res/xml-sw768dp-land/kbd_more_keys_keyboard_template.xml
java/res/xml-sw768dp-land/kbd_popup_template.xml
java/res/xml-sw768dp/kbd_more_keys_keyboard_template.xml
java/res/xml-sw768dp/kbd_popup_template.xml
java/res/xml-sw768dp/kbd_row3_right2.xml
java/res/xml-sw768dp/kbd_rows_qwerty.xml
java/res/xml-sw768dp/row_symbols_shift4.xml
java/res/xml-xlarge-land/kbd_popup_template.xml
java/res/xml-xlarge/kbd_key_styles.xml
java/res/xml-xlarge/kbd_popup_template.xml
java/res/xml-xlarge/kbd_qwerty_row1.xml
java/res/xml-xlarge/kbd_qwerty_row2.xml
java/res/xml-xlarge/kbd_qwerty_row3.xml
java/res/xml-xlarge/kbd_qwerty_row4.xml
java/res/xml-xlarge/kbd_row3_right2.xml
java/res/xml-xlarge/kbd_rows_arabic.xml
java/res/xml-xlarge/kbd_rows_azerty.xml
java/res/xml-xlarge/kbd_rows_hebrew.xml
java/res/xml-xlarge/kbd_rows_qwerty.xml
java/res/xml-xlarge/kbd_rows_qwertz.xml
java/res/xml-xlarge/kbd_rows_russian.xml
java/res/xml-xlarge/kbd_rows_scandinavian.xml
java/res/xml-xlarge/kbd_rows_serbian.xml
java/res/xml-xlarge/kbd_rows_spanish.xml
java/res/xml-xlarge/kbd_symbols.xml
java/res/xml-xlarge/kbd_symbols_shift.xml
java/res/xml/key_azerty_quote.xml
java/res/xml/key_f1.xml
java/res/xml/method.xml
java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java
java/src/com/android/inputmethod/latin/Utils.java
native/Android.mk
Change-Id: I96e8e042f636ed8e5cc023cf8514f13121e39195
Diffstat (limited to 'java/src/com/android/inputmethod/latin/StringUtils.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/StringUtils.java | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java new file mode 100644 index 000000000..a43b90525 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.Locale; + +public class StringUtils { + private StringUtils() { + // This utility class is not publicly instantiable. + } + + public static int codePointCount(String text) { + if (TextUtils.isEmpty(text)) return 0; + return text.codePointCount(0, text.length()); + } + + public static boolean containsInArray(String key, String[] array) { + for (final String element : array) { + if (key.equals(element)) return true; + } + return false; + } + + public static boolean containsInCsv(String key, String csv) { + if (TextUtils.isEmpty(csv)) return false; + return containsInArray(key, csv.split(",")); + } + + public static String appendToCsvIfNotExists(String key, String csv) { + if (TextUtils.isEmpty(csv)) return key; + if (containsInCsv(key, csv)) return csv; + return csv + "," + key; + } + + public static String removeFromCsvIfExists(String key, String csv) { + if (TextUtils.isEmpty(csv)) return ""; + final String[] elements = csv.split(","); + if (!containsInArray(key, elements)) return csv; + final ArrayList<String> result = new ArrayList<String>(elements.length - 1); + for (final String element : elements) { + if (!key.equals(element)) result.add(element); + } + return TextUtils.join(",", result); + } + + /** + * Returns true if a and b are equal ignoring the case of the character. + * @param a first character to check + * @param b second character to check + * @return {@code true} if a and b are equal, {@code false} otherwise. + */ + public static boolean equalsIgnoreCase(char a, char b) { + // Some language, such as Turkish, need testing both cases. + return a == b + || Character.toLowerCase(a) == Character.toLowerCase(b) + || Character.toUpperCase(a) == Character.toUpperCase(b); + } + + /** + * Returns true if a and b are equal ignoring the case of the characters, including if they are + * both null. + * @param a first CharSequence to check + * @param b second CharSequence to check + * @return {@code true} if a and b are equal, {@code false} otherwise. + */ + public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) { + if (a == b) + return true; // including both a and b are null. + if (a == null || b == null) + return false; + final int length = a.length(); + if (length != b.length()) + return false; + for (int i = 0; i < length; i++) { + if (!equalsIgnoreCase(a.charAt(i), b.charAt(i))) + return false; + } + return true; + } + + /** + * Returns true if a and b are equal ignoring the case of the characters, including if a is null + * and b is zero length. + * @param a CharSequence to check + * @param b character array to check + * @param offset start offset of array b + * @param length length of characters in array b + * @return {@code true} if a and b are equal, {@code false} otherwise. + * @throws IndexOutOfBoundsException + * if {@code offset < 0 || length < 0 || offset + length > data.length}. + * @throws NullPointerException if {@code b == null}. + */ + public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) { + if (offset < 0 || length < 0 || length > b.length - offset) + throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset + + " length=" + length); + if (a == null) + return length == 0; // including a is null and b is zero length. + if (a.length() != length) + return false; + for (int i = 0; i < length; i++) { + if (!equalsIgnoreCase(a.charAt(i), b[offset + i])) + return false; + } + return true; + } + + /** + * Returns true if cs contains any upper case characters. + * + * @param cs the CharSequence to check + * @return {@code true} if cs contains any upper case characters, {@code false} otherwise. + */ + public static boolean hasUpperCase(final CharSequence cs) { + final int length = cs.length(); + for (int i = 0, cp = 0; i < length; i += Character.charCount(cp)) { + cp = Character.codePointAt(cs, i); + if (Character.isUpperCase(cp)) { + return true; + } + } + return false; + } + + /** + * Remove duplicates from an array of strings. + * + * This method will always keep the first occurrence of all strings at their position + * in the array, removing the subsequent ones. + */ + public static void removeDupes(final ArrayList<CharSequence> suggestions) { + if (suggestions.size() < 2) return; + int i = 1; + // Don't cache suggestions.size(), since we may be removing items + while (i < suggestions.size()) { + final CharSequence cur = suggestions.get(i); + // Compare each suggestion with each previous suggestion + for (int j = 0; j < i; j++) { + CharSequence previous = suggestions.get(j); + if (TextUtils.equals(cur, previous)) { + suggestions.remove(i); + i--; + break; + } + } + i++; + } + } + + public static String toTitleCase(String s, Locale locale) { + if (s.length() <= 1) { + // TODO: is this really correct? Shouldn't this be s.toUpperCase()? + return s; + } + // TODO: fix the bugs below + // - This does not work for Greek, because it returns upper case instead of title case. + // - It does not work for Serbian, because it fails to account for the "lj" character, + // which should be "Lj" in title case and "LJ" in upper case. + // - It does not work for Dutch, because it fails to account for the "ij" digraph, which + // are two different characters but both should be capitalized as "IJ" as if they were + // a single letter. + // - It also does not work with unicode surrogate code points. + return s.toUpperCase(locale).charAt(0) + s.substring(1); + } + + public static int[] toCodePointArray(final String string) { + final char[] characters = string.toCharArray(); + final int length = characters.length; + final int[] codePoints = new int[Character.codePointCount(characters, 0, length)]; + int codePoint = Character.codePointAt(characters, 0); + int dsti = 0; + for (int srci = Character.charCount(codePoint); + srci < length; srci += Character.charCount(codePoint), ++dsti) { + codePoints[dsti] = codePoint; + codePoint = Character.codePointAt(characters, srci); + } + codePoints[dsti] = codePoint; + return codePoints; + } +} |