• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.inputmethod.latin;
18 
19 import android.text.TextUtils;
20 
21 import java.util.ArrayList;
22 import java.util.Locale;
23 
24 public class StringUtils {
StringUtils()25     private StringUtils() {
26         // This utility class is not publicly instantiable.
27     }
28 
codePointCount(String text)29     public static int codePointCount(String text) {
30         if (TextUtils.isEmpty(text)) return 0;
31         return text.codePointCount(0, text.length());
32     }
33 
containsInArray(String key, String[] array)34     public static boolean containsInArray(String key, String[] array) {
35         for (final String element : array) {
36             if (key.equals(element)) return true;
37         }
38         return false;
39     }
40 
containsInCsv(String key, String csv)41     public static boolean containsInCsv(String key, String csv) {
42         if (TextUtils.isEmpty(csv)) return false;
43         return containsInArray(key, csv.split(","));
44     }
45 
appendToCsvIfNotExists(String key, String csv)46     public static String appendToCsvIfNotExists(String key, String csv) {
47         if (TextUtils.isEmpty(csv)) return key;
48         if (containsInCsv(key, csv)) return csv;
49         return csv + "," + key;
50     }
51 
removeFromCsvIfExists(String key, String csv)52     public static String removeFromCsvIfExists(String key, String csv) {
53         if (TextUtils.isEmpty(csv)) return "";
54         final String[] elements = csv.split(",");
55         if (!containsInArray(key, elements)) return csv;
56         final ArrayList<String> result = new ArrayList<String>(elements.length - 1);
57         for (final String element : elements) {
58             if (!key.equals(element)) result.add(element);
59         }
60         return TextUtils.join(",", result);
61     }
62 
63     /**
64      * Returns true if a and b are equal ignoring the case of the character.
65      * @param a first character to check
66      * @param b second character to check
67      * @return {@code true} if a and b are equal, {@code false} otherwise.
68      */
equalsIgnoreCase(char a, char b)69     public static boolean equalsIgnoreCase(char a, char b) {
70         // Some language, such as Turkish, need testing both cases.
71         return a == b
72                 || Character.toLowerCase(a) == Character.toLowerCase(b)
73                 || Character.toUpperCase(a) == Character.toUpperCase(b);
74     }
75 
76     /**
77      * Returns true if a and b are equal ignoring the case of the characters, including if they are
78      * both null.
79      * @param a first CharSequence to check
80      * @param b second CharSequence to check
81      * @return {@code true} if a and b are equal, {@code false} otherwise.
82      */
equalsIgnoreCase(CharSequence a, CharSequence b)83     public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) {
84         if (a == b)
85             return true;  // including both a and b are null.
86         if (a == null || b == null)
87             return false;
88         final int length = a.length();
89         if (length != b.length())
90             return false;
91         for (int i = 0; i < length; i++) {
92             if (!equalsIgnoreCase(a.charAt(i), b.charAt(i)))
93                 return false;
94         }
95         return true;
96     }
97 
98     /**
99      * Returns true if a and b are equal ignoring the case of the characters, including if a is null
100      * and b is zero length.
101      * @param a CharSequence to check
102      * @param b character array to check
103      * @param offset start offset of array b
104      * @param length length of characters in array b
105      * @return {@code true} if a and b are equal, {@code false} otherwise.
106      * @throws IndexOutOfBoundsException
107      *   if {@code offset < 0 || length < 0 || offset + length > data.length}.
108      * @throws NullPointerException if {@code b == null}.
109      */
equalsIgnoreCase(CharSequence a, char[] b, int offset, int length)110     public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) {
111         if (offset < 0 || length < 0 || length > b.length - offset)
112             throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset
113                     + " length=" + length);
114         if (a == null)
115             return length == 0;  // including a is null and b is zero length.
116         if (a.length() != length)
117             return false;
118         for (int i = 0; i < length; i++) {
119             if (!equalsIgnoreCase(a.charAt(i), b[offset + i]))
120                 return false;
121         }
122         return true;
123     }
124 
125     /**
126      * Returns true if cs contains any upper case characters.
127      *
128      * @param cs the CharSequence to check
129      * @return {@code true} if cs contains any upper case characters, {@code false} otherwise.
130      */
hasUpperCase(final CharSequence cs)131     public static boolean hasUpperCase(final CharSequence cs) {
132         final int length = cs.length();
133         for (int i = 0, cp = 0; i < length; i += Character.charCount(cp)) {
134             cp = Character.codePointAt(cs, i);
135             if (Character.isUpperCase(cp)) {
136                 return true;
137             }
138         }
139         return false;
140     }
141 
142     /**
143      * Remove duplicates from an array of strings.
144      *
145      * This method will always keep the first occurrence of all strings at their position
146      * in the array, removing the subsequent ones.
147      */
removeDupes(final ArrayList<CharSequence> suggestions)148     public static void removeDupes(final ArrayList<CharSequence> suggestions) {
149         if (suggestions.size() < 2) return;
150         int i = 1;
151         // Don't cache suggestions.size(), since we may be removing items
152         while (i < suggestions.size()) {
153             final CharSequence cur = suggestions.get(i);
154             // Compare each suggestion with each previous suggestion
155             for (int j = 0; j < i; j++) {
156                 CharSequence previous = suggestions.get(j);
157                 if (TextUtils.equals(cur, previous)) {
158                     suggestions.remove(i);
159                     i--;
160                     break;
161                 }
162             }
163             i++;
164         }
165     }
166 
toTitleCase(String s, Locale locale)167     public static String toTitleCase(String s, Locale locale) {
168         if (s.length() <= 1) {
169             // TODO: is this really correct? Shouldn't this be s.toUpperCase()?
170             return s;
171         }
172         // TODO: fix the bugs below
173         // - This does not work for Greek, because it returns upper case instead of title case.
174         // - It does not work for Serbian, because it fails to account for the "lj" character,
175         // which should be "Lj" in title case and "LJ" in upper case.
176         // - It does not work for Dutch, because it fails to account for the "ij" digraph, which
177         // are two different characters but both should be capitalized as "IJ" as if they were
178         // a single letter.
179         // - It also does not work with unicode surrogate code points.
180         return s.toUpperCase(locale).charAt(0) + s.substring(1);
181     }
182 
toCodePointArray(final String string)183     public static int[] toCodePointArray(final String string) {
184         final char[] characters = string.toCharArray();
185         final int length = characters.length;
186         final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
187         int codePoint = Character.codePointAt(characters, 0);
188         int dsti = 0;
189         for (int srci = Character.charCount(codePoint);
190                 srci < length; srci += Character.charCount(codePoint), ++dsti) {
191             codePoints[dsti] = codePoint;
192             codePoint = Character.codePointAt(characters, srci);
193         }
194         codePoints[dsti] = codePoint;
195         return codePoints;
196     }
197 }
198