Merge "Prepare dictionary saving in native code."
commit
ac7e005ef0
|
@ -19,6 +19,7 @@ package com.android.inputmethod.latin;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.keyboard.ProximityInfo;
|
import com.android.inputmethod.keyboard.ProximityInfo;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.settings.NativeSuggestOptions;
|
import com.android.inputmethod.latin.settings.NativeSuggestOptions;
|
||||||
|
@ -47,6 +48,7 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
private long mNativeDict;
|
private long mNativeDict;
|
||||||
private final Locale mLocale;
|
private final Locale mLocale;
|
||||||
private final long mDictSize;
|
private final long mDictSize;
|
||||||
|
private final String mDictFilePath;
|
||||||
private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
|
private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
|
||||||
private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
|
private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
|
||||||
private final int[] mSpaceIndices = new int[MAX_RESULTS];
|
private final int[] mSpaceIndices = new int[MAX_RESULTS];
|
||||||
|
@ -91,6 +93,7 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
super(dictType);
|
super(dictType);
|
||||||
mLocale = locale;
|
mLocale = locale;
|
||||||
mDictSize = length;
|
mDictSize = length;
|
||||||
|
mDictFilePath = filename;
|
||||||
mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
|
mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
|
||||||
loadDictionary(filename, offset, length, isUpdatable);
|
loadDictionary(filename, offset, length, isUpdatable);
|
||||||
}
|
}
|
||||||
|
@ -101,6 +104,9 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
|
|
||||||
private static native long openNative(String sourceDir, long dictOffset, long dictSize,
|
private static native long openNative(String sourceDir, long dictOffset, long dictSize,
|
||||||
boolean isUpdatable);
|
boolean isUpdatable);
|
||||||
|
private static native void flushNative(long dict, String filePath);
|
||||||
|
private static native boolean needsToRunGCNative(long dict);
|
||||||
|
private static native void flushWithGCNative(long dict, String filePath);
|
||||||
private static native void closeNative(long dict);
|
private static native void closeNative(long dict);
|
||||||
private static native int getProbabilityNative(long dict, int[] word);
|
private static native int getProbabilityNative(long dict, int[] word);
|
||||||
private static native boolean isValidBigramNative(long dict, int[] word0, int[] word1);
|
private static native boolean isValidBigramNative(long dict, int[] word0, int[] word1);
|
||||||
|
@ -261,6 +267,24 @@ public final class BinaryDictionary extends Dictionary {
|
||||||
removeBigramWordsNative(mNativeDict, codePoints0, codePoints1);
|
removeBigramWordsNative(mNativeDict, codePoints0, codePoints1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UsedForTesting
|
||||||
|
public void flush() {
|
||||||
|
if (!isValidDictionary()) return;
|
||||||
|
flushNative(mNativeDict, mDictFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UsedForTesting
|
||||||
|
public void flushWithGC() {
|
||||||
|
if (!isValidDictionary()) return;
|
||||||
|
flushWithGCNative(mNativeDict, mDictFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UsedForTesting
|
||||||
|
public boolean needsToRunGC() {
|
||||||
|
if (!isValidDictionary()) return false;
|
||||||
|
return needsToRunGCNative(mNativeDict);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldAutoCommit(final SuggestedWordInfo candidate) {
|
public boolean shouldAutoCommit(final SuggestedWordInfo candidate) {
|
||||||
// TODO: actually use the confidence rather than use this completely broken heuristic
|
// TODO: actually use the confidence rather than use this completely broken heuristic
|
||||||
|
|
|
@ -46,8 +46,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring s
|
||||||
sourceDirChars[sourceDirUtf8Length] = '\0';
|
sourceDirChars[sourceDirUtf8Length] = '\0';
|
||||||
DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy =
|
DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy =
|
||||||
DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy(
|
DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy(
|
||||||
sourceDirChars, static_cast<int>(sourceDirUtf8Length),
|
sourceDirChars, static_cast<int>(dictOffset), static_cast<int>(dictSize),
|
||||||
static_cast<int>(dictOffset), static_cast<int>(dictSize),
|
|
||||||
isUpdatable == JNI_TRUE);
|
isUpdatable == JNI_TRUE);
|
||||||
if (!dictionaryStructureWithBufferPolicy) {
|
if (!dictionaryStructureWithBufferPolicy) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -59,6 +58,35 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring s
|
||||||
return reinterpret_cast<jlong>(dictionary);
|
return reinterpret_cast<jlong>(dictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void latinime_BinaryDictionary_flush(JNIEnv *env, jclass clazz, jlong dict,
|
||||||
|
jstring filePath) {
|
||||||
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
||||||
|
if (!dictionary) return;
|
||||||
|
const jsize filePathUtf8Length = env->GetStringUTFLength(filePath);
|
||||||
|
char filePathChars[filePathUtf8Length + 1];
|
||||||
|
env->GetStringUTFRegion(filePath, 0, env->GetStringLength(filePath), filePathChars);
|
||||||
|
filePathChars[filePathUtf8Length] = '\0';
|
||||||
|
dictionary->flush(filePathChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool latinime_BinaryDictionary_needsToRunGC(JNIEnv *env, jclass clazz,
|
||||||
|
jlong dict) {
|
||||||
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
||||||
|
if (!dictionary) return false;
|
||||||
|
return dictionary->needsToRunGC();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void latinime_BinaryDictionary_flushWithGC(JNIEnv *env, jclass clazz, jlong dict,
|
||||||
|
jstring filePath) {
|
||||||
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
||||||
|
if (!dictionary) return;
|
||||||
|
const jsize filePathUtf8Length = env->GetStringUTFLength(filePath);
|
||||||
|
char filePathChars[filePathUtf8Length + 1];
|
||||||
|
env->GetStringUTFRegion(filePath, 0, env->GetStringLength(filePath), filePathChars);
|
||||||
|
filePathChars[filePathUtf8Length] = '\0';
|
||||||
|
dictionary->flushWithGC(filePathChars);
|
||||||
|
}
|
||||||
|
|
||||||
static void latinime_BinaryDictionary_close(JNIEnv *env, jclass clazz, jlong dict) {
|
static void latinime_BinaryDictionary_close(JNIEnv *env, jclass clazz, jlong dict) {
|
||||||
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
||||||
if (!dictionary) return;
|
if (!dictionary) return;
|
||||||
|
@ -252,6 +280,21 @@ static const JNINativeMethod sMethods[] = {
|
||||||
const_cast<char *>("(J)V"),
|
const_cast<char *>("(J)V"),
|
||||||
reinterpret_cast<void *>(latinime_BinaryDictionary_close)
|
reinterpret_cast<void *>(latinime_BinaryDictionary_close)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
const_cast<char *>("flushNative"),
|
||||||
|
const_cast<char *>("(JLjava/lang/String;)V"),
|
||||||
|
reinterpret_cast<void *>(latinime_BinaryDictionary_flush)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
const_cast<char *>("needsToRunGCNative"),
|
||||||
|
const_cast<char *>("(J)Z"),
|
||||||
|
reinterpret_cast<void *>(latinime_BinaryDictionary_needsToRunGC)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
const_cast<char *>("flushWithGCNative"),
|
||||||
|
const_cast<char *>("(JLjava/lang/String;)V"),
|
||||||
|
reinterpret_cast<void *>(latinime_BinaryDictionary_flushWithGC)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
const_cast<char *>("getSuggestionsNative"),
|
const_cast<char *>("getSuggestionsNative"),
|
||||||
const_cast<char *>("(JJJ[I[I[I[I[III[I[I[I[I[I[I[I)I"),
|
const_cast<char *>("(JJJ[I[I[I[I[III[I[I[I[I[I[I[I)I"),
|
||||||
|
|
|
@ -112,6 +112,18 @@ void Dictionary::removeBigramWords(const int *const word0, const int length0,
|
||||||
mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1);
|
mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dictionary::flush(const char *const filePath) {
|
||||||
|
mDictionaryStructureWithBufferPolicy->flush(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dictionary::flushWithGC(const char *const filePath) {
|
||||||
|
mDictionaryStructureWithBufferPolicy->flushWithGC(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Dictionary::needsToRunGC() {
|
||||||
|
return mDictionaryStructureWithBufferPolicy->needsToRunGC();
|
||||||
|
}
|
||||||
|
|
||||||
void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
|
void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
|
||||||
const int BUFFER_SIZE = 16;
|
const int BUFFER_SIZE = 16;
|
||||||
int dictionaryIdCodePointBuffer[BUFFER_SIZE];
|
int dictionaryIdCodePointBuffer[BUFFER_SIZE];
|
||||||
|
|
|
@ -77,6 +77,12 @@ class Dictionary {
|
||||||
void removeBigramWords(const int *const word0, const int length0, const int *const word1,
|
void removeBigramWords(const int *const word0, const int length0, const int *const word1,
|
||||||
const int length1);
|
const int length1);
|
||||||
|
|
||||||
|
void flush(const char *const filePath);
|
||||||
|
|
||||||
|
void flushWithGC(const char *const filePath);
|
||||||
|
|
||||||
|
bool needsToRunGC();
|
||||||
|
|
||||||
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const {
|
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const {
|
||||||
return mDictionaryStructureWithBufferPolicy;
|
return mDictionaryStructureWithBufferPolicy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,12 @@ class DictionaryStructureWithBufferPolicy {
|
||||||
virtual bool removeBigramWords(const int *const word0, const int length0,
|
virtual bool removeBigramWords(const int *const word0, const int length0,
|
||||||
const int *const word1, const int length1) = 0;
|
const int *const word1, const int length1) = 0;
|
||||||
|
|
||||||
|
virtual void flush(const char *const filePath) = 0;
|
||||||
|
|
||||||
|
virtual void flushWithGC(const char *const filePath) = 0;
|
||||||
|
|
||||||
|
virtual bool needsToRunGC() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DictionaryStructureWithBufferPolicy() {}
|
DictionaryStructureWithBufferPolicy() {}
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,12 @@
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
/* static */ DictionaryStructureWithBufferPolicy *DictionaryStructureWithBufferPolicyFactory
|
/* static */ DictionaryStructureWithBufferPolicy *DictionaryStructureWithBufferPolicyFactory
|
||||||
::newDictionaryStructureWithBufferPolicy(const char *const path, const int pathLength,
|
::newDictionaryStructureWithBufferPolicy(const char *const path, const int bufOffset,
|
||||||
const int bufOffset, const int size, const bool isUpdatable) {
|
const int size, const bool isUpdatable) {
|
||||||
// Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
|
// Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
|
||||||
// impl classes of DictionaryStructureWithBufferPolicy.
|
// impl classes of DictionaryStructureWithBufferPolicy.
|
||||||
const MmappedBuffer *const mmapedBuffer = MmappedBuffer::openBuffer(path, pathLength, bufOffset,
|
const MmappedBuffer *const mmapedBuffer = MmappedBuffer::openBuffer(path, bufOffset, size,
|
||||||
size, isUpdatable);
|
isUpdatable);
|
||||||
if (!mmapedBuffer) {
|
if (!mmapedBuffer) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,7 @@ namespace latinime {
|
||||||
class DictionaryStructureWithBufferPolicyFactory {
|
class DictionaryStructureWithBufferPolicyFactory {
|
||||||
public:
|
public:
|
||||||
static DictionaryStructureWithBufferPolicy *newDictionaryStructureWithBufferPolicy(
|
static DictionaryStructureWithBufferPolicy *newDictionaryStructureWithBufferPolicy(
|
||||||
const char *const path, const int pathLength, const int bufOffset, const int size,
|
const char *const path, const int bufOffset, const int size, const bool isUpdatable);
|
||||||
const bool isUpdatable);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);
|
||||||
|
|
|
@ -243,4 +243,29 @@ bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const
|
||||||
return writingHelper.removeBigramWords(word0Pos, word1Pos);
|
return writingHelper.removeBigramWords(word0Pos, word1Pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicPatriciaTriePolicy::flush(const char *const filePath) {
|
||||||
|
if (!mBuffer->isUpdatable()) {
|
||||||
|
AKLOGI("Warning: flush() is called for non-updatable dictionary.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: Implement.
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) {
|
||||||
|
if (!mBuffer->isUpdatable()) {
|
||||||
|
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: Implement.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicPatriciaTriePolicy::needsToRunGC() const {
|
||||||
|
if (!mBuffer->isUpdatable()) {
|
||||||
|
AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO: Implement.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace latinime
|
} // namespace latinime
|
||||||
|
|
|
@ -85,6 +85,12 @@ class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
|
||||||
bool removeBigramWords(const int *const word0, const int length0, const int *const word1,
|
bool removeBigramWords(const int *const word0, const int length0, const int *const word1,
|
||||||
const int length1);
|
const int length1);
|
||||||
|
|
||||||
|
void flush(const char *const filePath);
|
||||||
|
|
||||||
|
void flushWithGC(const char *const filePath);
|
||||||
|
|
||||||
|
bool needsToRunGC() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTriePolicy);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTriePolicy);
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,22 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flush(const char *const filePath) {
|
||||||
|
// This method should not be called for non-updatable dictionary.
|
||||||
|
AKLOGI("Warning: flush() is called for non-updatable dictionary.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void flushWithGC(const char *const filePath) {
|
||||||
|
// This method should not be called for non-updatable dictionary.
|
||||||
|
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needsToRunGC() const {
|
||||||
|
// This method should not be called for non-updatable dictionary.
|
||||||
|
AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ namespace latinime {
|
||||||
|
|
||||||
class MmappedBuffer {
|
class MmappedBuffer {
|
||||||
public:
|
public:
|
||||||
static MmappedBuffer* openBuffer(const char *const path, const int pathLength,
|
static MmappedBuffer* openBuffer(const char *const path, const int bufferOffset,
|
||||||
const int bufferOffset, const int bufferSize, const bool isUpdatable) {
|
const int bufferSize, const bool isUpdatable) {
|
||||||
const int openMode = isUpdatable ? O_RDWR : O_RDONLY;
|
const int openMode = isUpdatable ? O_RDWR : O_RDONLY;
|
||||||
const int mmapFd = open(path, openMode);
|
const int mmapFd = open(path, openMode);
|
||||||
if (mmapFd < 0) {
|
if (mmapFd < 0) {
|
||||||
|
|
Loading…
Reference in New Issue