1 /*
2  * Copyright (C) 2015 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 package com.android.test.uibench;
17 
18 import android.icu.text.UnicodeSet;
19 import android.icu.text.UnicodeSetIterator;
20 
21 import java.util.ArrayList;
22 import java.util.Random;
23 
24 public class TextUtils {
25     private static final int STRING_COUNT = 200;
26     private static final int SIMPLE_STRING_LENGTH = 10;  // in code points
27 
UnicodeSetToArray(UnicodeSet set)28     private static String[] UnicodeSetToArray(UnicodeSet set) {
29         final UnicodeSetIterator iterator = new UnicodeSetIterator(set);
30         final ArrayList<String> out = new ArrayList<>(set.size());
31         while (iterator.next()) {
32             out.add(iterator.getString());
33         }
34         return out.toArray(new String[out.size()]);
35     }
36 
37     /**
38      * Create word of random assortment of lower/upper case letters
39      */
randomWord(Random random, int length)40     private static String randomWord(Random random, int length) {
41         String result = "";
42         for (int j = 0; j < length; j++) {
43             // add random letter
44             int base = random.nextInt(2) == 0 ? 'A' : 'a';
45             result += (char)(random.nextInt(26) + base);
46         }
47         return result;
48     }
49 
50     /**
51      * Create word from a random assortment of a given set of codepoints, given as strings.
52      */
randomWordFromStringSet(Random random, int length, String[] stringSet)53     private static String randomWordFromStringSet(Random random, int length, String[] stringSet) {
54         final StringBuilder sb = new StringBuilder(length);
55         final int setLength = stringSet.length;
56         for (int j = 0; j < length; j++) {
57             sb.append(stringSet[random.nextInt(setLength)]);
58         }
59         return sb.toString();
60     }
61 
buildSimpleStringList()62     public static String[] buildSimpleStringList() {
63         return buildSimpleStringList(SIMPLE_STRING_LENGTH);
64     }
65 
buildEmojiStringList()66     public static String[] buildEmojiStringList() {
67         return buildEmojiStringList(SIMPLE_STRING_LENGTH);
68     }
69 
buildHanStringList()70     public static String[] buildHanStringList() {
71         return buildHanStringList(SIMPLE_STRING_LENGTH);
72     }
73 
buildLongStringList()74     public static String[] buildLongStringList() {
75         return buildLongStringList(SIMPLE_STRING_LENGTH);
76     }
77 
buildSimpleStringList(int stringLength)78     public static String[] buildSimpleStringList(int stringLength) {
79         String[] strings = new String[STRING_COUNT];
80         Random random = new Random(0);
81         for (int i = 0; i < strings.length; i++) {
82             strings[i] = randomWord(random, stringLength);
83         }
84         return strings;
85     }
86 
buildStringListFromUnicodeSet(int stringLength, UnicodeSet set)87     private static String[] buildStringListFromUnicodeSet(int stringLength, UnicodeSet set) {
88         final String[] strings = new String[STRING_COUNT];
89         final Random random = new Random(0);
90         final String[] stringSet = UnicodeSetToArray(set);
91         for (int i = 0; i < strings.length; i++) {
92             strings[i] = randomWordFromStringSet(random, stringLength, stringSet);
93         }
94         return strings;
95     }
96 
buildEmojiStringList(int stringLength)97     public static String[] buildEmojiStringList(int stringLength) {
98         return buildStringListFromUnicodeSet(stringLength, new UnicodeSet("[:emoji:]"));
99     }
100 
buildHanStringList(int stringLength)101     public static String[] buildHanStringList(int stringLength) {
102         return buildStringListFromUnicodeSet(stringLength, new UnicodeSet("[\\u4E00-\\u9FA0]"));
103     }
104 
buildLongStringList(int stringLength)105     public static String[] buildLongStringList(int stringLength) {
106         final int WORD_COUNT = 100;
107         final String[] strings = new String[STRING_COUNT];
108         final Random random = new Random(0);
109         for (int i = 0; i < strings.length; i++) {
110             final StringBuilder sb = new StringBuilder((stringLength + 1) * WORD_COUNT);
111             for (int j = 0; j < WORD_COUNT; ++j) {
112                 if (j != 0) {
113                     sb.append(' ');
114                 }
115                 sb.append(randomWord(random, stringLength));
116             }
117             strings[i] = sb.toString();
118         }
119         return strings;
120     }
121 
122     // a small number of strings reused frequently, expected to hit
123     // in the word-granularity text layout cache
124     static final String[] CACHE_HIT_STRINGS = new String[] {
125             "a",
126             "small",
127             "number",
128             "of",
129             "strings",
130             "reused",
131             "frequently"
132     };
133 
134     private static final int WORDS_IN_PARAGRAPH = 150;
135 
136     // misses are fairly long 'words' to ensure they miss
137     private static final int PARAGRAPH_MISS_MIN_LENGTH = 4;
138     private static final int PARAGRAPH_MISS_MAX_LENGTH = 9;
139 
buildParagraphListWithHitPercentage(int hitPercentage)140     static String[] buildParagraphListWithHitPercentage(int hitPercentage) {
141         if (hitPercentage < 0 || hitPercentage > 100) throw new IllegalArgumentException();
142 
143         String[] strings = new String[STRING_COUNT];
144         Random random = new Random(0);
145         for (int i = 0; i < strings.length; i++) {
146             String result = "";
147             for (int word = 0; word < WORDS_IN_PARAGRAPH; word++) {
148                 if (word != 0) {
149                     result += " ";
150                 }
151                 if (random.nextInt(100) < hitPercentage) {
152                     // add a common word, which is very likely to hit in the cache
153                     result += CACHE_HIT_STRINGS[random.nextInt(CACHE_HIT_STRINGS.length)];
154                 } else {
155                     // construct a random word, which will *most likely* miss
156                     int length = PARAGRAPH_MISS_MIN_LENGTH;
157                     length += random.nextInt(PARAGRAPH_MISS_MAX_LENGTH - PARAGRAPH_MISS_MIN_LENGTH);
158 
159                     result += randomWord(random, length);
160                 }
161             }
162             strings[i] = result;
163         }
164 
165         return strings;
166     }
167 }
168