Loading java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +2 −2 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ final class BinaryDictionaryGetter { /** * Returns a file address from a resource, or null if it cannot be opened. */ private static AssetFileAddress loadFallbackResource(final Context context, public static AssetFileAddress loadFallbackResource(final Context context, final int fallbackResId) { final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId); if (afd == null) { Loading Loading @@ -149,7 +149,7 @@ final class BinaryDictionaryGetter { * @param context the context on which to open the files upon. * @return an array of binary dictionary files, which may be empty but may not be null. */ private static File[] getCachedWordLists(final String locale, final Context context) { public static File[] getCachedWordLists(final String locale, final Context context) { final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context); if (null == directoryList) return EMPTY_FILE_ARRAY; final HashMap<String, FileAndMatchLevel> cacheFiles = CollectionUtils.newHashMap(); Loading java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java +83 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.res.AssetManager; import android.content.res.Resources; import android.util.Log; Loading @@ -26,6 +27,7 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Locale; /** Loading @@ -41,6 +43,18 @@ public class DictionaryInfoUtils { // 6 digits - unicode is limited to 21 bits private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6; public static class DictionaryInfo { public final Locale mLocale; public final AssetFileAddress mFileAddress; public final int mVersion; public DictionaryInfo(final Locale locale, final AssetFileAddress fileAddress, final int version) { mLocale = locale; mFileAddress = fileAddress; mVersion = version; } } private DictionaryInfoUtils() { // Private constructor to forbid instantation of this helper class. } Loading Loading @@ -234,12 +248,79 @@ public class DictionaryInfoUtils { public static FileHeader getDictionaryFileHeaderOrNull(final File file) { try { final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeader(file); return header; return BinaryDictIOUtils.getDictionaryFileHeader(file, 0, file.length()); } catch (UnsupportedFormatException e) { return null; } catch (IOException e) { return null; } } private static DictionaryInfo createDictionaryInfoFromFileAddress( final AssetFileAddress fileAddress) { final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeaderOrNull( new File(fileAddress.mFilename), fileAddress.mOffset, fileAddress.mLength); final Locale locale = LocaleUtils.constructLocaleFromString(header.getLocaleString()); final String version = header.getVersion(); return new DictionaryInfo(locale, fileAddress, Integer.parseInt(version)); } private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList, final DictionaryInfo newElement) { for (final DictionaryInfo info : dictList) { if (info.mLocale.equals(newElement.mLocale)) { if (newElement.mVersion <= info.mVersion) { return; } dictList.remove(info); } } dictList.add(newElement); } public static ArrayList<DictionaryInfo> getCurrentDictionaryFileNameAndVersionInfo( final Context context) { final ArrayList<DictionaryInfo> dictList = CollectionUtils.newArrayList(); // Retrieve downloaded dictionaries final File[] directoryList = getCachedDirectoryList(context); for (final File directory : directoryList) { final String localeString = getWordListIdFromFileName(directory.getName()); File[] dicts = BinaryDictionaryGetter.getCachedWordLists(localeString, context); for (final File dict : dicts) { final String wordListId = getWordListIdFromFileName(dict.getName()); if (!DictionaryInfoUtils.isMainWordListId(wordListId)) continue; final Locale locale = LocaleUtils.constructLocaleFromString(localeString); final AssetFileAddress fileAddress = AssetFileAddress.makeFromFile(dict); final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress); // Protect against cases of a less-specific dictionary being found, like an // en dictionary being used for an en_US locale. In this case, the en dictionary // should be used for en_US but discounted for listing purposes. if (!dictionaryInfo.mLocale.equals(locale)) continue; addOrUpdateDictInfo(dictList, dictionaryInfo); } } // Retrieve files from assets final Resources resources = context.getResources(); final AssetManager assets = resources.getAssets(); for (final String localeString : assets.getLocales()) { final Locale locale = LocaleUtils.constructLocaleFromString(localeString); final int resourceId = DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale( context.getResources(), locale); if (0 == resourceId) continue; final AssetFileAddress fileAddress = BinaryDictionaryGetter.loadFallbackResource(context, resourceId); final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress); // Protect against cases of a less-specific dictionary being found, like an // en dictionary being used for an en_US locale. In this case, the en dictionary // should be used for en_US but discounted for listing purposes. if (!dictionaryInfo.mLocale.equals(locale)) continue; addOrUpdateDictInfo(dictList, dictionaryInfo); } return dictList; } } java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java +3 −7 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import java.util.Locale; public class ExternalDictionaryGetterForDebug { private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath() + "/Download"; private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale"; private static String[] findDictionariesInTheDownloadedFolder() { final File[] files = new File(SOURCE_FOLDER).listFiles(); Loading Loading @@ -90,8 +89,7 @@ public class ExternalDictionaryGetterForDebug { final File file = new File(SOURCE_FOLDER, fileName.toString()); final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file); final StringBuilder message = new StringBuilder(); final String locale = header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE); final String locale = header.getLocaleString(); for (String key : header.mDictionaryOptions.mAttributes.keySet()) { message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key)); message.append("\n"); Loading Loading @@ -123,13 +121,11 @@ public class ExternalDictionaryGetterForDebug { BufferedOutputStream outputStream = null; File tempFile = null; try { final String locale = header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE); final String locale = header.getLocaleString(); // Create the id for a main dictionary for this locale final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY + BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale; final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context); final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context); final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); tempFile = new File(tempFileName); tempFile.delete(); Loading java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +18 −3 Original line number Diff line number Diff line Loading @@ -988,9 +988,12 @@ public final class BinaryDictIOUtils { * This is quite resource intensive - don't call when performance is critical. * * @param file The file to read. * @param offset The offset in the file where to start reading the data. * @param length The length of the data file. */ private static final int HEADER_READING_BUFFER_SIZE = 16384; public static FileHeader getDictionaryFileHeader(final File file) public static FileHeader getDictionaryFileHeader( final File file, final long offset, final long length) throws FileNotFoundException, IOException, UnsupportedFormatException { final byte[] buffer = new byte[HEADER_READING_BUFFER_SIZE]; final FileInputStream inStream = new FileInputStream(file); Loading @@ -998,10 +1001,22 @@ public final class BinaryDictIOUtils { inStream.read(buffer); final BinaryDictInputOutput.ByteBufferWrapper wrapper = new BinaryDictInputOutput.ByteBufferWrapper(inStream.getChannel().map( FileChannel.MapMode.READ_ONLY, 0, file.length())); FileChannel.MapMode.READ_ONLY, offset, length)); return BinaryDictInputOutput.readHeader(wrapper); } finally { inStream.close(); } } public static FileHeader getDictionaryFileHeaderOrNull(final File file, final long offset, final long length) { try { final FileHeader header = getDictionaryFileHeader(file, offset, length); return header; } catch (UnsupportedFormatException e) { return null; } catch (IOException e) { return null; } } } java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +12 −0 Original line number Diff line number Diff line Loading @@ -256,12 +256,24 @@ public final class FormatSpec { public final int mHeaderSize; public final DictionaryOptions mDictionaryOptions; public final FormatOptions mFormatOptions; private static final String DICTIONARY_VERSION_ATTRIBUTE = "version"; private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale"; public FileHeader(final int headerSize, final DictionaryOptions dictionaryOptions, final FormatOptions formatOptions) { mHeaderSize = headerSize; mDictionaryOptions = dictionaryOptions; mFormatOptions = formatOptions; } // Helper method to get the locale as a String public String getLocaleString() { return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_LOCALE_ATTRIBUTE); } // Helper method to get the version String public String getVersion() { return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_VERSION_ATTRIBUTE); } } private FormatSpec() { Loading Loading
java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +2 −2 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ final class BinaryDictionaryGetter { /** * Returns a file address from a resource, or null if it cannot be opened. */ private static AssetFileAddress loadFallbackResource(final Context context, public static AssetFileAddress loadFallbackResource(final Context context, final int fallbackResId) { final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId); if (afd == null) { Loading Loading @@ -149,7 +149,7 @@ final class BinaryDictionaryGetter { * @param context the context on which to open the files upon. * @return an array of binary dictionary files, which may be empty but may not be null. */ private static File[] getCachedWordLists(final String locale, final Context context) { public static File[] getCachedWordLists(final String locale, final Context context) { final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context); if (null == directoryList) return EMPTY_FILE_ARRAY; final HashMap<String, FileAndMatchLevel> cacheFiles = CollectionUtils.newHashMap(); Loading
java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java +83 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.res.AssetManager; import android.content.res.Resources; import android.util.Log; Loading @@ -26,6 +27,7 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Locale; /** Loading @@ -41,6 +43,18 @@ public class DictionaryInfoUtils { // 6 digits - unicode is limited to 21 bits private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6; public static class DictionaryInfo { public final Locale mLocale; public final AssetFileAddress mFileAddress; public final int mVersion; public DictionaryInfo(final Locale locale, final AssetFileAddress fileAddress, final int version) { mLocale = locale; mFileAddress = fileAddress; mVersion = version; } } private DictionaryInfoUtils() { // Private constructor to forbid instantation of this helper class. } Loading Loading @@ -234,12 +248,79 @@ public class DictionaryInfoUtils { public static FileHeader getDictionaryFileHeaderOrNull(final File file) { try { final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeader(file); return header; return BinaryDictIOUtils.getDictionaryFileHeader(file, 0, file.length()); } catch (UnsupportedFormatException e) { return null; } catch (IOException e) { return null; } } private static DictionaryInfo createDictionaryInfoFromFileAddress( final AssetFileAddress fileAddress) { final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeaderOrNull( new File(fileAddress.mFilename), fileAddress.mOffset, fileAddress.mLength); final Locale locale = LocaleUtils.constructLocaleFromString(header.getLocaleString()); final String version = header.getVersion(); return new DictionaryInfo(locale, fileAddress, Integer.parseInt(version)); } private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList, final DictionaryInfo newElement) { for (final DictionaryInfo info : dictList) { if (info.mLocale.equals(newElement.mLocale)) { if (newElement.mVersion <= info.mVersion) { return; } dictList.remove(info); } } dictList.add(newElement); } public static ArrayList<DictionaryInfo> getCurrentDictionaryFileNameAndVersionInfo( final Context context) { final ArrayList<DictionaryInfo> dictList = CollectionUtils.newArrayList(); // Retrieve downloaded dictionaries final File[] directoryList = getCachedDirectoryList(context); for (final File directory : directoryList) { final String localeString = getWordListIdFromFileName(directory.getName()); File[] dicts = BinaryDictionaryGetter.getCachedWordLists(localeString, context); for (final File dict : dicts) { final String wordListId = getWordListIdFromFileName(dict.getName()); if (!DictionaryInfoUtils.isMainWordListId(wordListId)) continue; final Locale locale = LocaleUtils.constructLocaleFromString(localeString); final AssetFileAddress fileAddress = AssetFileAddress.makeFromFile(dict); final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress); // Protect against cases of a less-specific dictionary being found, like an // en dictionary being used for an en_US locale. In this case, the en dictionary // should be used for en_US but discounted for listing purposes. if (!dictionaryInfo.mLocale.equals(locale)) continue; addOrUpdateDictInfo(dictList, dictionaryInfo); } } // Retrieve files from assets final Resources resources = context.getResources(); final AssetManager assets = resources.getAssets(); for (final String localeString : assets.getLocales()) { final Locale locale = LocaleUtils.constructLocaleFromString(localeString); final int resourceId = DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale( context.getResources(), locale); if (0 == resourceId) continue; final AssetFileAddress fileAddress = BinaryDictionaryGetter.loadFallbackResource(context, resourceId); final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress); // Protect against cases of a less-specific dictionary being found, like an // en dictionary being used for an en_US locale. In this case, the en dictionary // should be used for en_US but discounted for listing purposes. if (!dictionaryInfo.mLocale.equals(locale)) continue; addOrUpdateDictInfo(dictList, dictionaryInfo); } return dictList; } }
java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java +3 −7 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import java.util.Locale; public class ExternalDictionaryGetterForDebug { private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath() + "/Download"; private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale"; private static String[] findDictionariesInTheDownloadedFolder() { final File[] files = new File(SOURCE_FOLDER).listFiles(); Loading Loading @@ -90,8 +89,7 @@ public class ExternalDictionaryGetterForDebug { final File file = new File(SOURCE_FOLDER, fileName.toString()); final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file); final StringBuilder message = new StringBuilder(); final String locale = header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE); final String locale = header.getLocaleString(); for (String key : header.mDictionaryOptions.mAttributes.keySet()) { message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key)); message.append("\n"); Loading Loading @@ -123,13 +121,11 @@ public class ExternalDictionaryGetterForDebug { BufferedOutputStream outputStream = null; File tempFile = null; try { final String locale = header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE); final String locale = header.getLocaleString(); // Create the id for a main dictionary for this locale final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY + BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale; final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context); final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context); final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context); tempFile = new File(tempFileName); tempFile.delete(); Loading
java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +18 −3 Original line number Diff line number Diff line Loading @@ -988,9 +988,12 @@ public final class BinaryDictIOUtils { * This is quite resource intensive - don't call when performance is critical. * * @param file The file to read. * @param offset The offset in the file where to start reading the data. * @param length The length of the data file. */ private static final int HEADER_READING_BUFFER_SIZE = 16384; public static FileHeader getDictionaryFileHeader(final File file) public static FileHeader getDictionaryFileHeader( final File file, final long offset, final long length) throws FileNotFoundException, IOException, UnsupportedFormatException { final byte[] buffer = new byte[HEADER_READING_BUFFER_SIZE]; final FileInputStream inStream = new FileInputStream(file); Loading @@ -998,10 +1001,22 @@ public final class BinaryDictIOUtils { inStream.read(buffer); final BinaryDictInputOutput.ByteBufferWrapper wrapper = new BinaryDictInputOutput.ByteBufferWrapper(inStream.getChannel().map( FileChannel.MapMode.READ_ONLY, 0, file.length())); FileChannel.MapMode.READ_ONLY, offset, length)); return BinaryDictInputOutput.readHeader(wrapper); } finally { inStream.close(); } } public static FileHeader getDictionaryFileHeaderOrNull(final File file, final long offset, final long length) { try { final FileHeader header = getDictionaryFileHeader(file, offset, length); return header; } catch (UnsupportedFormatException e) { return null; } catch (IOException e) { return null; } } }
java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +12 −0 Original line number Diff line number Diff line Loading @@ -256,12 +256,24 @@ public final class FormatSpec { public final int mHeaderSize; public final DictionaryOptions mDictionaryOptions; public final FormatOptions mFormatOptions; private static final String DICTIONARY_VERSION_ATTRIBUTE = "version"; private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale"; public FileHeader(final int headerSize, final DictionaryOptions dictionaryOptions, final FormatOptions formatOptions) { mHeaderSize = headerSize; mDictionaryOptions = dictionaryOptions; mFormatOptions = formatOptions; } // Helper method to get the locale as a String public String getLocaleString() { return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_LOCALE_ATTRIBUTE); } // Helper method to get the version String public String getVersion() { return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_VERSION_ATTRIBUTE); } } private FormatSpec() { Loading