Optimize KeyboardTextsTable
This change counts all occurrences of each string resource and sort those in descending order of the occurrence. Change-Id: I726402157feb0d436a54bd0a7252acd17fd711f9main
parent
8dd47029f1
commit
0fe4d00068
File diff suppressed because it is too large
Load Diff
|
@ -63,6 +63,7 @@ public final class KeyboardTextsTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] NAMES = {
|
private static final String[] NAMES = {
|
||||||
|
// /* index:histogram */ "name",
|
||||||
/* @NAMES@ */
|
/* @NAMES@ */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,22 @@ public class ArrayInitializerFormatter {
|
||||||
private final PrintStream mOut;
|
private final PrintStream mOut;
|
||||||
private final int mMaxWidth;
|
private final int mMaxWidth;
|
||||||
private final String mIndent;
|
private final String mIndent;
|
||||||
|
// String resource names array; indexed by {@link #CurrentIndex} and
|
||||||
|
// {@link #mStartIndexOfBuffer}.
|
||||||
|
private final String[] mResourceNames;
|
||||||
|
|
||||||
private int mCurrentIndex = 0;
|
private int mCurrentIndex = 0;
|
||||||
private String mFixedElement;
|
private String mLastElement;
|
||||||
private final StringBuilder mBuffer = new StringBuilder();
|
private final StringBuilder mBuffer = new StringBuilder();
|
||||||
private int mBufferedLen;
|
private int mBufferedLen;
|
||||||
private int mBufferedIndex = Integer.MIN_VALUE;
|
private int mStartIndexOfBuffer = Integer.MIN_VALUE;
|
||||||
|
|
||||||
public ArrayInitializerFormatter(final PrintStream out, final int width, final String indent) {
|
public ArrayInitializerFormatter(final PrintStream out, final int width, final String indent,
|
||||||
|
final String[] resourceNames) {
|
||||||
mOut = out;
|
mOut = out;
|
||||||
mMaxWidth = width - indent.length();
|
mMaxWidth = width - indent.length();
|
||||||
mIndent = indent;
|
mIndent = indent;
|
||||||
|
mResourceNames = resourceNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCurrentIndex() {
|
public int getCurrentIndex() {
|
||||||
|
@ -44,20 +49,24 @@ public class ArrayInitializerFormatter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int lastIndex = mCurrentIndex - 1;
|
final int lastIndex = mCurrentIndex - 1;
|
||||||
if (mBufferedIndex == lastIndex) {
|
if (mStartIndexOfBuffer == lastIndex) {
|
||||||
mOut.format("%s/* %d */ %s\n", mIndent, mBufferedIndex, mBuffer);
|
mOut.format("%s/* %s */ %s\n",
|
||||||
} else if (mBufferedIndex == lastIndex - 1) {
|
mIndent, mResourceNames[mStartIndexOfBuffer], mBuffer);
|
||||||
final String[] elements = mBuffer.toString().split(" ");
|
} else if (mStartIndexOfBuffer == lastIndex - 1) {
|
||||||
mOut.format("%s/* %d */ %s\n"
|
final String startElement = mBuffer.toString()
|
||||||
+ "%s/* %d */ %s\n",
|
.substring(0, mBuffer.length() - mLastElement.length())
|
||||||
mIndent, mBufferedIndex, elements[0],
|
.trim();
|
||||||
mIndent, lastIndex, elements[1]);
|
mOut.format("%s/* %s */ %s\n"
|
||||||
|
+ "%s/* %s */ %s\n",
|
||||||
|
mIndent, mResourceNames[mStartIndexOfBuffer], startElement,
|
||||||
|
mIndent, mResourceNames[lastIndex], mLastElement);
|
||||||
} else {
|
} else {
|
||||||
mOut.format("%s/* %d~ */\n"
|
mOut.format("%s/* %s ~ */\n"
|
||||||
+ "%s%s\n"
|
+ "%s%s\n"
|
||||||
+ "%s/* ~%d */\n", mIndent, mBufferedIndex,
|
+ "%s/* ~ %s */\n",
|
||||||
|
mIndent, mResourceNames[mStartIndexOfBuffer],
|
||||||
mIndent, mBuffer,
|
mIndent, mBuffer,
|
||||||
mIndent, lastIndex);
|
mIndent, mResourceNames[lastIndex]);
|
||||||
}
|
}
|
||||||
mBuffer.setLength(0);
|
mBuffer.setLength(0);
|
||||||
mBufferedLen = 0;
|
mBufferedLen = 0;
|
||||||
|
@ -66,20 +75,22 @@ public class ArrayInitializerFormatter {
|
||||||
public void outCommentLines(final String lines) {
|
public void outCommentLines(final String lines) {
|
||||||
flush();
|
flush();
|
||||||
mOut.print(lines);
|
mOut.print(lines);
|
||||||
mFixedElement = null;
|
mLastElement = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void outElement(final String element) {
|
public void outElement(final String element) {
|
||||||
if (!element.equals(mFixedElement)) {
|
if (!element.equals(mLastElement)) {
|
||||||
flush();
|
flush();
|
||||||
mBufferedIndex = mCurrentIndex;
|
mStartIndexOfBuffer = mCurrentIndex;
|
||||||
}
|
}
|
||||||
final int nextLen = mBufferedLen + " ".length() + element.length();
|
final int nextLen = mBufferedLen + " ".length() + element.length();
|
||||||
if (mBufferedLen != 0 && nextLen < mMaxWidth) {
|
if (mBufferedLen != 0 && nextLen < mMaxWidth) {
|
||||||
|
// Element can fit in the current line.
|
||||||
mBuffer.append(' ');
|
mBuffer.append(' ');
|
||||||
mBuffer.append(element);
|
mBuffer.append(element);
|
||||||
mBufferedLen = nextLen;
|
mBufferedLen = nextLen;
|
||||||
} else {
|
} else {
|
||||||
|
// Element should be on the next line.
|
||||||
if (mBufferedLen != 0) {
|
if (mBufferedLen != 0) {
|
||||||
mBuffer.append('\n');
|
mBuffer.append('\n');
|
||||||
mBuffer.append(mIndent);
|
mBuffer.append(mIndent);
|
||||||
|
@ -88,6 +99,6 @@ public class ArrayInitializerFormatter {
|
||||||
mBufferedLen = element.length();
|
mBufferedLen = element.length();
|
||||||
}
|
}
|
||||||
mCurrentIndex++;
|
mCurrentIndex++;
|
||||||
mFixedElement = element;
|
mLastElement = element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.io.LineNumberReader;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
@ -47,8 +48,19 @@ public class MoreKeysResources {
|
||||||
// Language to string resources map.
|
// Language to string resources map.
|
||||||
private final HashMap<String, StringResourceMap> mResourcesMap =
|
private final HashMap<String, StringResourceMap> mResourcesMap =
|
||||||
new HashMap<String, StringResourceMap>();
|
new HashMap<String, StringResourceMap>();
|
||||||
// Name to id map.
|
// Sorted languages list. The language is taken from string resource directories
|
||||||
private final HashMap<String, Integer> mNameToIdMap = new HashMap<String,Integer>();
|
// (values-<language>/) or {@link #DEFAULT_LANGUAGE_NAME} for the default string resource
|
||||||
|
// directory (values/).
|
||||||
|
private final ArrayList<String> mSortedLanguagesList = new ArrayList<String>();
|
||||||
|
// Default string resources map.
|
||||||
|
private final StringResourceMap mDefaultResourceMap;
|
||||||
|
// Histogram of string resource names. This is used to sort {@link #mSortedResourceNames}.
|
||||||
|
private final HashMap<String, Integer> mNameHistogram = new HashMap<String, Integer>();
|
||||||
|
// Sorted string resource names array; Descending order of histogram count.
|
||||||
|
// The string resource name is specified as an attribute "name" in string resource files.
|
||||||
|
// The string resource can be accessed by specifying name "!text/<name>"
|
||||||
|
// via {@link KeyboardTextsSet#getText(String)}.
|
||||||
|
private final String[] mSortedResourceNames;
|
||||||
|
|
||||||
public MoreKeysResources(final JarFile jar) {
|
public MoreKeysResources(final JarFile jar) {
|
||||||
mJar = jar;
|
mJar = jar;
|
||||||
|
@ -65,6 +77,45 @@ public class MoreKeysResources {
|
||||||
close(stream);
|
close(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mDefaultResourceMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME);
|
||||||
|
mSortedLanguagesList.addAll(mResourcesMap.keySet());
|
||||||
|
Collections.sort(mSortedLanguagesList);
|
||||||
|
|
||||||
|
// Initialize name histogram and names list.
|
||||||
|
final HashMap<String, Integer> nameHistogram = mNameHistogram;
|
||||||
|
final ArrayList<String> resourceNamesList = new ArrayList<String>();
|
||||||
|
for (final StringResource res : mDefaultResourceMap.getResources()) {
|
||||||
|
nameHistogram.put(res.mName, 0); // Initialize histogram value.
|
||||||
|
resourceNamesList.add(res.mName);
|
||||||
|
}
|
||||||
|
// Make name histogram.
|
||||||
|
for (final String language : mResourcesMap.keySet()) {
|
||||||
|
final StringResourceMap resMap = mResourcesMap.get(language);
|
||||||
|
if (resMap == mDefaultResourceMap) continue;
|
||||||
|
for (final StringResource res : resMap.getResources()) {
|
||||||
|
if (!mDefaultResourceMap.contains(res.mName)) {
|
||||||
|
throw new RuntimeException(res.mName + " in " + language
|
||||||
|
+ " doesn't have default resource");
|
||||||
|
}
|
||||||
|
final int histogramValue = nameHistogram.get(res.mName);
|
||||||
|
nameHistogram.put(res.mName, histogramValue + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort names list.
|
||||||
|
Collections.sort(resourceNamesList, new Comparator<String>() {
|
||||||
|
@Override
|
||||||
|
public int compare(final String leftName, final String rightName) {
|
||||||
|
final int leftCount = nameHistogram.get(leftName);
|
||||||
|
final int rightCount = nameHistogram.get(rightName);
|
||||||
|
// Descending order of histogram count.
|
||||||
|
if (leftCount > rightCount) return -1;
|
||||||
|
if (leftCount < rightCount) return 1;
|
||||||
|
// TODO: Add further criteria to order the same histogram value names to be able to
|
||||||
|
// minimize footprints of string resources arrays.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mSortedResourceNames = resourceNamesList.toArray(new String[resourceNamesList.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getLanguageFromResDir(final String dirName) {
|
private static String getLanguageFromResDir(final String dirName) {
|
||||||
|
@ -132,19 +183,17 @@ public class MoreKeysResources {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpNames(final PrintStream out) {
|
private void dumpNames(final PrintStream out) {
|
||||||
final StringResourceMap defaultResMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME);
|
final int namesCount = mSortedResourceNames.length;
|
||||||
int id = 0;
|
for (int index = 0; index < namesCount; index++) {
|
||||||
for (final StringResource res : defaultResMap.getResources()) {
|
final String name = mSortedResourceNames[index];
|
||||||
out.format(" /* %2d */ \"%s\",\n", id, res.mName);
|
final int histogramValue = mNameHistogram.get(name);
|
||||||
mNameToIdMap.put(res.mName, id);
|
out.format(" /* %3d:%2d */ \"%s\",\n", index, histogramValue, name);
|
||||||
id++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpDefaultTexts(final PrintStream out) {
|
private void dumpDefaultTexts(final PrintStream out) {
|
||||||
final StringResourceMap defaultResMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME);
|
final int outputArraySize = dumpTextsInternal(out, mDefaultResourceMap);
|
||||||
final int outputArraySize = dumpTextsInternal(out, defaultResMap, defaultResMap);
|
mDefaultResourceMap.setOutputArraySize(outputArraySize);
|
||||||
defaultResMap.setOutputArraySize(outputArraySize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getArrayNameForLanguage(final String language) {
|
private static String getArrayNameForLanguage(final String language) {
|
||||||
|
@ -152,35 +201,20 @@ public class MoreKeysResources {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpTexts(final PrintStream out) {
|
private void dumpTexts(final PrintStream out) {
|
||||||
final StringResourceMap defaultResMap = mResourcesMap.get(DEFAULT_LANGUAGE_NAME);
|
for (final String language : mSortedLanguagesList) {
|
||||||
final ArrayList<String> allLanguages = new ArrayList<String>();
|
final StringResourceMap resMap = mResourcesMap.get(language);
|
||||||
allLanguages.addAll(mResourcesMap.keySet());
|
if (resMap == mDefaultResourceMap) continue;
|
||||||
Collections.sort(allLanguages);
|
|
||||||
for (final String language : allLanguages) {
|
|
||||||
if (language.equals(DEFAULT_LANGUAGE_NAME)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out.format(" /* Language %s: %s */\n", language, getLanguageDisplayName(language));
|
out.format(" /* Language %s: %s */\n", language, getLanguageDisplayName(language));
|
||||||
out.format(" private static final String[] " + getArrayNameForLanguage(language)
|
out.format(" private static final String[] " + getArrayNameForLanguage(language)
|
||||||
+ " = {\n");
|
+ " = {\n");
|
||||||
final StringResourceMap resMap = mResourcesMap.get(language);
|
final int outputArraySize = dumpTextsInternal(out, resMap);
|
||||||
for (final StringResource res : resMap.getResources()) {
|
|
||||||
if (!defaultResMap.contains(res.mName)) {
|
|
||||||
throw new RuntimeException(res.mName + " in " + language
|
|
||||||
+ " doesn't have default resource");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final int outputArraySize = dumpTextsInternal(out, resMap, defaultResMap);
|
|
||||||
resMap.setOutputArraySize(outputArraySize);
|
resMap.setOutputArraySize(outputArraySize);
|
||||||
out.format(" };\n\n");
|
out.format(" };\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpLanguageMap(final PrintStream out) {
|
private void dumpLanguageMap(final PrintStream out) {
|
||||||
final ArrayList<String> allLanguages = new ArrayList<String>();
|
for (final String language : mSortedLanguagesList) {
|
||||||
allLanguages.addAll(mResourcesMap.keySet());
|
|
||||||
Collections.sort(allLanguages);
|
|
||||||
for (final String language : allLanguages) {
|
|
||||||
final StringResourceMap resMap = mResourcesMap.get(language);
|
final StringResourceMap resMap = mResourcesMap.get(language);
|
||||||
final Locale locale = LocaleUtils.constructLocaleFromString(language);
|
final Locale locale = LocaleUtils.constructLocaleFromString(language);
|
||||||
final String languageKeyToDump = locale.getCountry().isEmpty()
|
final String languageKeyToDump = locale.getCountry().isEmpty()
|
||||||
|
@ -201,15 +235,17 @@ public class MoreKeysResources {
|
||||||
return locale.getDisplayName(Locale.ENGLISH);
|
return locale.getDisplayName(Locale.ENGLISH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int dumpTextsInternal(final PrintStream out, final StringResourceMap resMap,
|
private int dumpTextsInternal(final PrintStream out, final StringResourceMap resMap) {
|
||||||
final StringResourceMap defaultResMap) {
|
|
||||||
final ArrayInitializerFormatter formatter =
|
final ArrayInitializerFormatter formatter =
|
||||||
new ArrayInitializerFormatter(out, 100, " ");
|
new ArrayInitializerFormatter(out, 100, " ", mSortedResourceNames);
|
||||||
int outputArraySize = 0;
|
int outputArraySize = 0;
|
||||||
boolean successiveNull = false;
|
boolean successiveNull = false;
|
||||||
for (final StringResource defaultRes : defaultResMap.getResources()) {
|
final int namesCount = mSortedResourceNames.length;
|
||||||
if (resMap.contains(defaultRes.mName)) {
|
for (int index = 0; index < namesCount; index++) {
|
||||||
final StringResource res = resMap.get(defaultRes.mName);
|
final String name = mSortedResourceNames[index];
|
||||||
|
final StringResource res = resMap.get(name);
|
||||||
|
if (res != null) {
|
||||||
|
// TODO: Check whether the resource value is equal to the default.
|
||||||
if (res.mComment != null) {
|
if (res.mComment != null) {
|
||||||
formatter.outCommentLines(addPrefix(" // ", res. mComment));
|
formatter.outCommentLines(addPrefix(" // ", res. mComment));
|
||||||
}
|
}
|
||||||
|
@ -270,7 +306,7 @@ public class MoreKeysResources {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void close(Closeable stream) {
|
private static void close(final Closeable stream) {
|
||||||
try {
|
try {
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
stream.close();
|
stream.close();
|
||||||
|
|
Loading…
Reference in New Issue