2014-03-05 09:19:34 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 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.utils;
|
|
|
|
|
|
|
|
import com.android.inputmethod.annotations.UsedForTesting;
|
2014-03-05 10:42:53 +00:00
|
|
|
import com.android.inputmethod.latin.BinaryDictionary;
|
|
|
|
import com.android.inputmethod.latin.makedict.DictionaryHeader;
|
|
|
|
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
|
2014-03-05 09:19:34 +00:00
|
|
|
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
|
|
|
|
|
2014-03-05 10:42:53 +00:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
2014-03-05 09:19:34 +00:00
|
|
|
import java.util.Locale;
|
|
|
|
import java.util.Map;
|
2014-03-27 08:46:35 +00:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
2014-03-05 09:19:34 +00:00
|
|
|
|
|
|
|
public final class BinaryDictionaryUtils {
|
|
|
|
private static final String TAG = BinaryDictionaryUtils.class.getSimpleName();
|
|
|
|
|
|
|
|
private BinaryDictionaryUtils() {
|
|
|
|
// This utility class is not publicly instantiable.
|
|
|
|
}
|
|
|
|
|
|
|
|
static {
|
|
|
|
JniUtils.loadNativeLibrary();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static native boolean createEmptyDictFileNative(String filePath, long dictVersion,
|
|
|
|
String locale, String[] attributeKeyStringArray, String[] attributeValueStringArray);
|
|
|
|
private static native float calcNormalizedScoreNative(int[] before, int[] after, int score);
|
|
|
|
private static native int setCurrentTimeForTestNative(int currentTime);
|
|
|
|
|
2014-03-05 10:42:53 +00:00
|
|
|
public static DictionaryHeader getHeader(final File dictFile)
|
|
|
|
throws IOException, UnsupportedFormatException {
|
|
|
|
return getHeaderWithOffsetAndLength(dictFile, 0 /* offset */, dictFile.length());
|
|
|
|
}
|
|
|
|
|
|
|
|
public static DictionaryHeader getHeaderWithOffsetAndLength(final File dictFile,
|
|
|
|
final long offset, final long length) throws IOException, UnsupportedFormatException {
|
|
|
|
// dictType is never used for reading the header. Passing an empty string.
|
|
|
|
final BinaryDictionary binaryDictionary = new BinaryDictionary(
|
|
|
|
dictFile.getAbsolutePath(), offset, length,
|
|
|
|
true /* useFullEditDistance */, null /* locale */, "" /* dictType */,
|
|
|
|
false /* isUpdatable */);
|
|
|
|
final DictionaryHeader header = binaryDictionary.getHeader();
|
|
|
|
binaryDictionary.close();
|
|
|
|
if (header == null) {
|
|
|
|
throw new IOException();
|
|
|
|
}
|
|
|
|
return header;
|
|
|
|
}
|
|
|
|
|
2014-03-27 08:46:35 +00:00
|
|
|
public static boolean renameDict(final File dictFile, final File newDictFile) {
|
|
|
|
if (dictFile.isFile()) {
|
|
|
|
return dictFile.renameTo(newDictFile);
|
|
|
|
} else if (dictFile.isDirectory()) {
|
|
|
|
final String dictName = dictFile.getName();
|
|
|
|
final String newDictName = newDictFile.getName();
|
|
|
|
if (newDictFile.exists()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (final File file : dictFile.listFiles()) {
|
|
|
|
if (!file.isFile()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
final String fileName = file.getName();
|
|
|
|
final String newFileName = fileName.replaceFirst(
|
|
|
|
Pattern.quote(dictName), Matcher.quoteReplacement(newDictName));
|
|
|
|
if (!file.renameTo(new File(dictFile, newFileName))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dictFile.renameTo(newDictFile);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-04-22 03:03:00 +00:00
|
|
|
@UsedForTesting
|
2014-03-05 09:19:34 +00:00
|
|
|
public static boolean createEmptyDictFile(final String filePath, final long dictVersion,
|
|
|
|
final Locale locale, final Map<String, String> attributeMap) {
|
|
|
|
final String[] keyArray = new String[attributeMap.size()];
|
|
|
|
final String[] valueArray = new String[attributeMap.size()];
|
|
|
|
int index = 0;
|
|
|
|
for (final String key : attributeMap.keySet()) {
|
|
|
|
keyArray[index] = key;
|
|
|
|
valueArray[index] = attributeMap.get(key);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
return createEmptyDictFileNative(filePath, dictVersion, locale.toString(), keyArray,
|
|
|
|
valueArray);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static float calcNormalizedScore(final String before, final String after,
|
|
|
|
final int score) {
|
|
|
|
return calcNormalizedScoreNative(StringUtils.toCodePointArray(before),
|
|
|
|
StringUtils.toCodePointArray(after), score);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Control the current time to be used in the native code. If currentTime >= 0, this method sets
|
|
|
|
* the current time and gets into test mode.
|
|
|
|
* In test mode, set timestamp is used as the current time in the native code.
|
|
|
|
* If currentTime < 0, quit the test mode and returns to using time() to get the current time.
|
|
|
|
*
|
|
|
|
* @param currentTime seconds since the unix epoch
|
|
|
|
* @return current time got in the native code.
|
|
|
|
*/
|
|
|
|
@UsedForTesting
|
|
|
|
public static int setCurrentTimeForTest(final int currentTime) {
|
|
|
|
final int currentNativeTimestamp = setCurrentTimeForTestNative(currentTime);
|
|
|
|
PersonalizationHelper.currentTimeChangedForTesting(currentNativeTimestamp);
|
|
|
|
return currentNativeTimestamp;
|
|
|
|
}
|
|
|
|
}
|