2009-03-13 22:11:42 +00:00
|
|
|
/*
|
2013-01-08 08:57:26 +00:00
|
|
|
* Copyright (C) 2009 The Android Open Source Project
|
2012-07-25 08:51:43 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
2013-01-08 08:57:26 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2012-07-25 08:51:43 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2009-03-13 22:11:42 +00:00
|
|
|
|
2011-02-22 08:28:55 +00:00
|
|
|
#define LOG_TAG "LatinIME: jni: BinaryDictionary"
|
2011-01-07 06:01:51 +00:00
|
|
|
|
2013-06-04 10:16:47 +00:00
|
|
|
#include "com_android_inputmethod_latin_BinaryDictionary.h"
|
2009-03-13 22:11:42 +00:00
|
|
|
|
2013-06-04 10:16:47 +00:00
|
|
|
#include <cstring> // for memset()
|
2013-05-30 15:02:57 +00:00
|
|
|
|
2013-06-04 10:16:47 +00:00
|
|
|
#include "defines.h"
|
2012-08-10 08:16:39 +00:00
|
|
|
#include "jni.h"
|
|
|
|
#include "jni_common.h"
|
2013-05-30 15:02:57 +00:00
|
|
|
#include "suggest/core/dictionary/dictionary.h"
|
2014-01-31 02:06:42 +00:00
|
|
|
#include "suggest/core/dictionary/word_property.h"
|
2014-03-07 10:36:19 +00:00
|
|
|
#include "suggest/core/result/suggestion_results.h"
|
2013-06-03 01:36:00 +00:00
|
|
|
#include "suggest/core/suggest_options.h"
|
2013-12-13 08:09:16 +00:00
|
|
|
#include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
|
2014-02-04 14:51:05 +00:00
|
|
|
#include "utils/char_utils.h"
|
2014-01-15 22:55:57 +00:00
|
|
|
#include "utils/time_keeper.h"
|
2012-08-10 08:16:39 +00:00
|
|
|
|
2011-02-22 08:28:55 +00:00
|
|
|
namespace latinime {
|
2009-03-13 22:11:42 +00:00
|
|
|
|
2012-08-01 09:03:55 +00:00
|
|
|
class ProximityInfo;
|
|
|
|
|
2013-01-11 16:18:00 +00:00
|
|
|
static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring sourceDir,
|
2013-06-25 05:25:01 +00:00
|
|
|
jlong dictOffset, jlong dictSize, jboolean isUpdatable) {
|
2011-01-07 06:01:51 +00:00
|
|
|
PROF_OPEN;
|
|
|
|
PROF_START(66);
|
2012-08-09 14:23:35 +00:00
|
|
|
const jsize sourceDirUtf8Length = env->GetStringUTFLength(sourceDir);
|
|
|
|
if (sourceDirUtf8Length <= 0) {
|
2012-01-13 09:01:22 +00:00
|
|
|
AKLOGE("DICT: Can't get sourceDir string");
|
2011-01-07 06:01:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2012-08-09 14:23:35 +00:00
|
|
|
char sourceDirChars[sourceDirUtf8Length + 1];
|
|
|
|
env->GetStringUTFRegion(sourceDir, 0, env->GetStringLength(sourceDir), sourceDirChars);
|
|
|
|
sourceDirChars[sourceDirUtf8Length] = '\0';
|
2014-03-06 14:36:38 +00:00
|
|
|
DictionaryStructureWithBufferPolicy::StructurePolicyPtr dictionaryStructureWithBufferPolicy(
|
2013-08-16 03:52:04 +00:00
|
|
|
DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy(
|
2013-09-17 09:07:16 +00:00
|
|
|
sourceDirChars, static_cast<int>(dictOffset), static_cast<int>(dictSize),
|
2014-03-06 14:36:38 +00:00
|
|
|
isUpdatable == JNI_TRUE));
|
|
|
|
if (!dictionaryStructureWithBufferPolicy) {
|
2013-08-15 11:37:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2013-08-16 03:52:04 +00:00
|
|
|
|
2014-03-06 14:36:38 +00:00
|
|
|
Dictionary *const dictionary =
|
|
|
|
new Dictionary(env, std::move(dictionaryStructureWithBufferPolicy));
|
2011-01-07 06:01:51 +00:00
|
|
|
PROF_END(66);
|
|
|
|
PROF_CLOSE;
|
2013-01-29 16:04:42 +00:00
|
|
|
return reinterpret_cast<jlong>(dictionary);
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
|
|
|
|
2013-09-17 09:07:16 +00:00
|
|
|
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,
|
2013-09-30 04:57:54 +00:00
|
|
|
jlong dict, jboolean mindsBlockByGC) {
|
2013-09-17 09:07:16 +00:00
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) return false;
|
2013-09-30 04:57:54 +00:00
|
|
|
return dictionary->needsToRunGC(mindsBlockByGC == JNI_TRUE);
|
2013-09-17 09:07:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-06-26 14:06:14 +00:00
|
|
|
static void latinime_BinaryDictionary_close(JNIEnv *env, jclass clazz, jlong dict) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) return;
|
|
|
|
delete dictionary;
|
|
|
|
}
|
|
|
|
|
2014-02-04 12:39:44 +00:00
|
|
|
static void latinime_BinaryDictionary_getHeaderInfo(JNIEnv *env, jclass clazz, jlong dict,
|
|
|
|
jintArray outHeaderSize, jintArray outFormatVersion, jobject outAttributeKeys,
|
|
|
|
jobject outAttributeValues) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) return;
|
2014-02-06 08:55:45 +00:00
|
|
|
const DictionaryHeaderStructurePolicy *const headerPolicy =
|
|
|
|
dictionary->getDictionaryStructurePolicy()->getHeaderStructurePolicy();
|
|
|
|
const int headerSize = headerPolicy->getSize();
|
|
|
|
env->SetIntArrayRegion(outHeaderSize, 0 /* start */, 1 /* len */, &headerSize);
|
|
|
|
const int formatVersion = headerPolicy->getFormatVersionNumber();
|
2014-02-04 12:39:44 +00:00
|
|
|
env->SetIntArrayRegion(outFormatVersion, 0 /* start */, 1 /* len */, &formatVersion);
|
2014-02-06 08:55:45 +00:00
|
|
|
// Output attribute map
|
|
|
|
jclass arrayListClass = env->FindClass("java/util/ArrayList");
|
|
|
|
jmethodID addMethodId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
|
|
|
|
const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap =
|
|
|
|
headerPolicy->getAttributeMap();
|
|
|
|
for (DictionaryHeaderStructurePolicy::AttributeMap::const_iterator it = attributeMap->begin();
|
|
|
|
it != attributeMap->end(); ++it) {
|
|
|
|
// Output key
|
|
|
|
jintArray keyCodePointArray = env->NewIntArray(it->first.size());
|
|
|
|
env->SetIntArrayRegion(
|
|
|
|
keyCodePointArray, 0 /* start */, it->first.size(), &it->first.at(0));
|
2014-02-18 14:40:03 +00:00
|
|
|
env->CallBooleanMethod(outAttributeKeys, addMethodId, keyCodePointArray);
|
2014-02-06 08:55:45 +00:00
|
|
|
env->DeleteLocalRef(keyCodePointArray);
|
|
|
|
// Output value
|
|
|
|
jintArray valueCodePointArray = env->NewIntArray(it->second.size());
|
|
|
|
env->SetIntArrayRegion(
|
|
|
|
valueCodePointArray, 0 /* start */, it->second.size(), &it->second.at(0));
|
2014-02-18 14:40:03 +00:00
|
|
|
env->CallBooleanMethod(outAttributeValues, addMethodId, valueCodePointArray);
|
2014-02-06 08:55:45 +00:00
|
|
|
env->DeleteLocalRef(valueCodePointArray);
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(arrayListClass);
|
2014-02-04 12:39:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-13 08:09:16 +00:00
|
|
|
static int latinime_BinaryDictionary_getFormatVersion(JNIEnv *env, jclass clazz, jlong dict) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) return 0;
|
2014-02-06 08:55:45 +00:00
|
|
|
const DictionaryHeaderStructurePolicy *const headerPolicy =
|
|
|
|
dictionary->getDictionaryStructurePolicy()->getHeaderStructurePolicy();
|
|
|
|
return headerPolicy->getFormatVersionNumber();
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
|
2014-03-07 10:36:19 +00:00
|
|
|
static void latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jclass clazz, jlong dict,
|
2012-08-08 12:23:25 +00:00
|
|
|
jlong proximityInfo, jlong dicTraverseSession, jintArray xCoordinatesArray,
|
2012-08-10 08:16:39 +00:00
|
|
|
jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdsArray,
|
2014-03-20 09:47:45 +00:00
|
|
|
jintArray inputCodePointsArray, jint inputSize, jintArray suggestOptions,
|
2014-03-07 10:36:19 +00:00
|
|
|
jintArray prevWordCodePointsForBigrams, jintArray outSuggestionCount,
|
|
|
|
jintArray outCodePointsArray, jintArray outScoresArray, jintArray outSpaceIndicesArray,
|
|
|
|
jintArray outTypesArray, jintArray outAutoCommitFirstWordConfidenceArray) {
|
2012-08-14 05:22:27 +00:00
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
2014-03-07 10:36:19 +00:00
|
|
|
// Assign 0 to outSuggestionCount here in case of returning earlier in this method.
|
|
|
|
int count = 0;
|
|
|
|
env->SetIntArrayRegion(outSuggestionCount, 0, 1 /* len */, &count);
|
|
|
|
if (!dictionary) {
|
|
|
|
return;
|
|
|
|
}
|
2012-08-14 05:22:27 +00:00
|
|
|
ProximityInfo *pInfo = reinterpret_cast<ProximityInfo *>(proximityInfo);
|
2013-06-03 07:12:20 +00:00
|
|
|
DicTraverseSession *traverseSession =
|
|
|
|
reinterpret_cast<DicTraverseSession *>(dicTraverseSession);
|
2012-08-10 08:16:39 +00:00
|
|
|
|
|
|
|
// Input values
|
2013-01-11 16:18:00 +00:00
|
|
|
int xCoordinates[inputSize];
|
|
|
|
int yCoordinates[inputSize];
|
|
|
|
int times[inputSize];
|
|
|
|
int pointerIds[inputSize];
|
2012-08-10 08:16:39 +00:00
|
|
|
const jsize inputCodePointsLength = env->GetArrayLength(inputCodePointsArray);
|
|
|
|
int inputCodePoints[inputCodePointsLength];
|
|
|
|
const jsize prevWordCodePointsLength =
|
|
|
|
prevWordCodePointsForBigrams ? env->GetArrayLength(prevWordCodePointsForBigrams) : 0;
|
|
|
|
int prevWordCodePointsInternal[prevWordCodePointsLength];
|
2014-03-07 01:04:44 +00:00
|
|
|
int *prevWordCodePoints = nullptr;
|
2013-01-11 16:18:00 +00:00
|
|
|
env->GetIntArrayRegion(xCoordinatesArray, 0, inputSize, xCoordinates);
|
|
|
|
env->GetIntArrayRegion(yCoordinatesArray, 0, inputSize, yCoordinates);
|
|
|
|
env->GetIntArrayRegion(timesArray, 0, inputSize, times);
|
|
|
|
env->GetIntArrayRegion(pointerIdsArray, 0, inputSize, pointerIds);
|
2012-08-10 08:16:39 +00:00
|
|
|
env->GetIntArrayRegion(inputCodePointsArray, 0, inputCodePointsLength, inputCodePoints);
|
|
|
|
if (prevWordCodePointsForBigrams) {
|
|
|
|
env->GetIntArrayRegion(prevWordCodePointsForBigrams, 0, prevWordCodePointsLength,
|
|
|
|
prevWordCodePointsInternal);
|
|
|
|
prevWordCodePoints = prevWordCodePointsInternal;
|
|
|
|
}
|
|
|
|
|
2013-05-24 17:21:04 +00:00
|
|
|
const jsize numberOfOptions = env->GetArrayLength(suggestOptions);
|
|
|
|
int options[numberOfOptions];
|
|
|
|
env->GetIntArrayRegion(suggestOptions, 0, numberOfOptions, options);
|
2013-05-30 00:18:03 +00:00
|
|
|
SuggestOptions givenSuggestOptions(options, numberOfOptions);
|
2013-05-24 17:21:04 +00:00
|
|
|
|
2012-08-10 08:16:39 +00:00
|
|
|
// Output values
|
2013-01-11 16:18:00 +00:00
|
|
|
/* By the way, let's check the output array length here to make sure */
|
2014-03-07 10:36:19 +00:00
|
|
|
const jsize outputCodePointsLength = env->GetArrayLength(outCodePointsArray);
|
2013-01-11 16:18:00 +00:00
|
|
|
if (outputCodePointsLength != (MAX_WORD_LENGTH * MAX_RESULTS)) {
|
|
|
|
AKLOGE("Invalid outputCodePointsLength: %d", outputCodePointsLength);
|
|
|
|
ASSERT(false);
|
2014-03-07 10:36:19 +00:00
|
|
|
return;
|
2013-01-11 16:18:00 +00:00
|
|
|
}
|
2014-03-07 10:36:19 +00:00
|
|
|
const jsize scoresLength = env->GetArrayLength(outScoresArray);
|
2013-01-11 16:18:00 +00:00
|
|
|
if (scoresLength != MAX_RESULTS) {
|
|
|
|
AKLOGE("Invalid scoresLength: %d", scoresLength);
|
2013-01-11 09:59:01 +00:00
|
|
|
ASSERT(false);
|
2014-03-07 10:36:19 +00:00
|
|
|
return;
|
2013-01-11 09:59:01 +00:00
|
|
|
}
|
2013-01-11 16:18:00 +00:00
|
|
|
int outputCodePoints[outputCodePointsLength];
|
2012-08-10 08:16:39 +00:00
|
|
|
int scores[scoresLength];
|
2014-03-07 10:36:19 +00:00
|
|
|
const jsize spaceIndicesLength = env->GetArrayLength(outSpaceIndicesArray);
|
2012-08-10 08:16:39 +00:00
|
|
|
int spaceIndices[spaceIndicesLength];
|
2014-03-07 10:36:19 +00:00
|
|
|
const jsize outputTypesLength = env->GetArrayLength(outTypesArray);
|
2012-08-10 08:16:39 +00:00
|
|
|
int outputTypes[outputTypesLength];
|
2013-09-30 12:39:43 +00:00
|
|
|
const jsize outputAutoCommitFirstWordConfidenceLength =
|
2014-03-07 10:36:19 +00:00
|
|
|
env->GetArrayLength(outAutoCommitFirstWordConfidenceArray);
|
2013-09-30 12:39:43 +00:00
|
|
|
// We only use the first result, as obviously we will only ever autocommit the first one
|
|
|
|
ASSERT(outputAutoCommitFirstWordConfidenceLength == 1);
|
|
|
|
int outputAutoCommitFirstWordConfidence[outputAutoCommitFirstWordConfidenceLength];
|
2012-10-29 09:06:22 +00:00
|
|
|
memset(outputCodePoints, 0, sizeof(outputCodePoints));
|
2012-08-24 05:51:15 +00:00
|
|
|
memset(scores, 0, sizeof(scores));
|
|
|
|
memset(spaceIndices, 0, sizeof(spaceIndices));
|
|
|
|
memset(outputTypes, 0, sizeof(outputTypes));
|
2013-09-30 12:39:43 +00:00
|
|
|
memset(outputAutoCommitFirstWordConfidence, 0, sizeof(outputAutoCommitFirstWordConfidence));
|
2012-07-11 03:07:44 +00:00
|
|
|
|
2013-05-30 00:18:03 +00:00
|
|
|
if (givenSuggestOptions.isGesture() || inputSize > 0) {
|
2014-03-07 10:36:19 +00:00
|
|
|
// TODO: Use SuggestionResults to return suggestions.
|
2012-08-08 12:23:25 +00:00
|
|
|
count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates,
|
2013-01-11 16:18:00 +00:00
|
|
|
times, pointerIds, inputCodePoints, inputSize, prevWordCodePoints,
|
2014-03-20 09:47:45 +00:00
|
|
|
prevWordCodePointsLength, &givenSuggestOptions, outputCodePoints,
|
2013-09-30 12:39:43 +00:00
|
|
|
scores, spaceIndices, outputTypes, outputAutoCommitFirstWordConfidence);
|
2012-07-11 03:07:44 +00:00
|
|
|
} else {
|
2014-03-07 10:36:19 +00:00
|
|
|
SuggestionResults suggestionResults(MAX_RESULTS);
|
|
|
|
dictionary->getPredictions(prevWordCodePoints, prevWordCodePointsLength,
|
|
|
|
&suggestionResults);
|
|
|
|
suggestionResults.outputSuggestions(env, outSuggestionCount, outCodePointsArray,
|
|
|
|
outScoresArray, outSpaceIndicesArray, outTypesArray,
|
|
|
|
outAutoCommitFirstWordConfidenceArray);
|
|
|
|
return;
|
2012-07-11 03:07:44 +00:00
|
|
|
}
|
|
|
|
|
2012-08-10 08:16:39 +00:00
|
|
|
// Copy back the output values
|
2014-03-07 10:36:19 +00:00
|
|
|
env->SetIntArrayRegion(outSuggestionCount, 0, 1 /* len */, &count);
|
|
|
|
env->SetIntArrayRegion(outCodePointsArray, 0, outputCodePointsLength, outputCodePoints);
|
|
|
|
env->SetIntArrayRegion(outScoresArray, 0, scoresLength, scores);
|
|
|
|
env->SetIntArrayRegion(outSpaceIndicesArray, 0, spaceIndicesLength, spaceIndices);
|
|
|
|
env->SetIntArrayRegion(outTypesArray, 0, outputTypesLength, outputTypes);
|
|
|
|
env->SetIntArrayRegion(outAutoCommitFirstWordConfidenceArray, 0,
|
2013-09-30 12:39:43 +00:00
|
|
|
outputAutoCommitFirstWordConfidenceLength, outputAutoCommitFirstWordConfidence);
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
|
|
|
|
2013-03-18 04:08:31 +00:00
|
|
|
static jint latinime_BinaryDictionary_getProbability(JNIEnv *env, jclass clazz, jlong dict,
|
2013-06-26 03:51:33 +00:00
|
|
|
jintArray word) {
|
2012-08-14 05:22:27 +00:00
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
2013-07-03 11:12:38 +00:00
|
|
|
if (!dictionary) return NOT_A_PROBABILITY;
|
2013-06-26 03:51:33 +00:00
|
|
|
const jsize wordLength = env->GetArrayLength(word);
|
|
|
|
int codePoints[wordLength];
|
|
|
|
env->GetIntArrayRegion(word, 0, wordLength, codePoints);
|
|
|
|
return dictionary->getProbability(codePoints, wordLength);
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
|
|
|
|
2013-09-18 02:18:28 +00:00
|
|
|
static jint latinime_BinaryDictionary_getBigramProbability(JNIEnv *env, jclass clazz,
|
|
|
|
jlong dict, jintArray word0, jintArray word1) {
|
2012-08-14 05:22:27 +00:00
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
2013-01-29 16:04:42 +00:00
|
|
|
if (!dictionary) return JNI_FALSE;
|
2013-06-26 03:51:33 +00:00
|
|
|
const jsize word0Length = env->GetArrayLength(word0);
|
|
|
|
const jsize word1Length = env->GetArrayLength(word1);
|
|
|
|
int word0CodePoints[word0Length];
|
|
|
|
int word1CodePoints[word1Length];
|
|
|
|
env->GetIntArrayRegion(word0, 0, word0Length, word0CodePoints);
|
|
|
|
env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
|
2013-09-18 02:18:28 +00:00
|
|
|
return dictionary->getBigramProbability(word0CodePoints, word0Length, word1CodePoints,
|
|
|
|
word1Length);
|
2012-04-27 06:50:21 +00:00
|
|
|
}
|
|
|
|
|
2014-02-03 05:51:58 +00:00
|
|
|
// Method to iterate all words in the dictionary for makedict.
|
|
|
|
// If token is 0, this method newly starts iterating the dictionary. This method returns 0 when
|
|
|
|
// the dictionary does not have a next word.
|
|
|
|
static jint latinime_BinaryDictionary_getNextWord(JNIEnv *env, jclass clazz,
|
|
|
|
jlong dict, jint token, jintArray outCodePoints) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) return 0;
|
|
|
|
const jsize outCodePointsLength = env->GetArrayLength(outCodePoints);
|
|
|
|
if (outCodePointsLength != MAX_WORD_LENGTH) {
|
|
|
|
AKLOGE("Invalid outCodePointsLength: %d", outCodePointsLength);
|
|
|
|
ASSERT(false);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int wordCodePoints[outCodePointsLength];
|
|
|
|
memset(wordCodePoints, 0, sizeof(wordCodePoints));
|
|
|
|
const int nextToken = dictionary->getNextWordAndNextToken(token, wordCodePoints);
|
|
|
|
env->SetIntArrayRegion(outCodePoints, 0, outCodePointsLength, wordCodePoints);
|
|
|
|
return nextToken;
|
|
|
|
}
|
|
|
|
|
2014-01-31 02:06:42 +00:00
|
|
|
static void latinime_BinaryDictionary_getWordProperty(JNIEnv *env, jclass clazz,
|
2013-12-13 08:09:16 +00:00
|
|
|
jlong dict, jintArray word, jintArray outCodePoints, jbooleanArray outFlags,
|
2014-01-31 11:32:44 +00:00
|
|
|
jintArray outProbabilityInfo, jobject outBigramTargets, jobject outBigramProbabilityInfo,
|
|
|
|
jobject outShortcutTargets, jobject outShortcutProbabilities) {
|
2013-12-13 08:09:16 +00:00
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) return;
|
|
|
|
const jsize wordLength = env->GetArrayLength(word);
|
|
|
|
int wordCodePoints[wordLength];
|
|
|
|
env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
|
2014-01-31 02:06:42 +00:00
|
|
|
const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints, wordLength);
|
2014-01-31 11:32:44 +00:00
|
|
|
wordProperty.outputProperties(env, outCodePoints, outFlags, outProbabilityInfo,
|
|
|
|
outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
|
|
|
|
outShortcutProbabilities);
|
2013-12-13 08:09:16 +00:00
|
|
|
}
|
|
|
|
|
2013-06-26 03:51:33 +00:00
|
|
|
static void latinime_BinaryDictionary_addUnigramWord(JNIEnv *env, jclass clazz, jlong dict,
|
2013-12-13 08:09:16 +00:00
|
|
|
jintArray word, jint probability, jintArray shortcutTarget, jint shortuctProbability,
|
|
|
|
jboolean isNotAWord, jboolean isBlacklisted, jint timestamp) {
|
2013-06-26 03:51:33 +00:00
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
jsize wordLength = env->GetArrayLength(word);
|
|
|
|
int codePoints[wordLength];
|
2013-09-10 09:45:39 +00:00
|
|
|
env->GetIntArrayRegion(word, 0, wordLength, codePoints);
|
2013-12-13 08:09:16 +00:00
|
|
|
jsize shortcutLength = shortcutTarget ? env->GetArrayLength(shortcutTarget) : 0;
|
|
|
|
int shortcutTargetCodePoints[shortcutLength];
|
|
|
|
if (shortcutTarget) {
|
|
|
|
env->GetIntArrayRegion(shortcutTarget, 0, shortcutLength, shortcutTargetCodePoints);
|
|
|
|
}
|
|
|
|
dictionary->addUnigramWord(codePoints, wordLength, probability, shortcutTargetCodePoints,
|
|
|
|
shortcutLength, shortuctProbability, isNotAWord, isBlacklisted, timestamp);
|
2013-06-26 03:51:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void latinime_BinaryDictionary_addBigramWords(JNIEnv *env, jclass clazz, jlong dict,
|
2013-12-13 08:09:16 +00:00
|
|
|
jintArray word0, jintArray word1, jint probability, jint timestamp) {
|
2013-06-26 03:51:33 +00:00
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
jsize word0Length = env->GetArrayLength(word0);
|
|
|
|
int word0CodePoints[word0Length];
|
2013-09-10 09:45:39 +00:00
|
|
|
env->GetIntArrayRegion(word0, 0, word0Length, word0CodePoints);
|
2013-06-26 03:51:33 +00:00
|
|
|
jsize word1Length = env->GetArrayLength(word1);
|
|
|
|
int word1CodePoints[word1Length];
|
2013-09-10 09:45:39 +00:00
|
|
|
env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
|
2013-06-26 03:51:33 +00:00
|
|
|
dictionary->addBigramWords(word0CodePoints, word0Length, word1CodePoints,
|
2013-12-13 08:09:16 +00:00
|
|
|
word1Length, probability, timestamp);
|
2013-06-26 03:51:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void latinime_BinaryDictionary_removeBigramWords(JNIEnv *env, jclass clazz, jlong dict,
|
|
|
|
jintArray word0, jintArray word1) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
jsize word0Length = env->GetArrayLength(word0);
|
|
|
|
int word0CodePoints[word0Length];
|
2013-09-10 09:45:39 +00:00
|
|
|
env->GetIntArrayRegion(word0, 0, word0Length, word0CodePoints);
|
2013-06-26 03:51:33 +00:00
|
|
|
jsize word1Length = env->GetArrayLength(word1);
|
|
|
|
int word1CodePoints[word1Length];
|
2013-09-10 09:45:39 +00:00
|
|
|
env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
|
2013-06-26 03:51:33 +00:00
|
|
|
dictionary->removeBigramWords(word0CodePoints, word0Length, word1CodePoints,
|
|
|
|
word1Length);
|
|
|
|
}
|
|
|
|
|
2013-12-13 08:09:16 +00:00
|
|
|
// Returns how many language model params are processed.
|
|
|
|
static int latinime_BinaryDictionary_addMultipleDictionaryEntries(JNIEnv *env, jclass clazz,
|
|
|
|
jlong dict, jobjectArray languageModelParams, jint startIndex) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
jsize languageModelParamCount = env->GetArrayLength(languageModelParams);
|
|
|
|
if (languageModelParamCount == 0 || startIndex >= languageModelParamCount) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
jobject languageModelParam = env->GetObjectArrayElement(languageModelParams, 0);
|
|
|
|
jclass languageModelParamClass = env->GetObjectClass(languageModelParam);
|
|
|
|
env->DeleteLocalRef(languageModelParam);
|
|
|
|
|
|
|
|
jfieldID word0FieldId = env->GetFieldID(languageModelParamClass, "mWord0", "[I");
|
|
|
|
jfieldID word1FieldId = env->GetFieldID(languageModelParamClass, "mWord1", "[I");
|
|
|
|
jfieldID unigramProbabilityFieldId =
|
|
|
|
env->GetFieldID(languageModelParamClass, "mUnigramProbability", "I");
|
|
|
|
jfieldID bigramProbabilityFieldId =
|
|
|
|
env->GetFieldID(languageModelParamClass, "mBigramProbability", "I");
|
|
|
|
jfieldID timestampFieldId =
|
|
|
|
env->GetFieldID(languageModelParamClass, "mTimestamp", "I");
|
|
|
|
jfieldID shortcutTargetFieldId =
|
|
|
|
env->GetFieldID(languageModelParamClass, "mShortcutTarget", "[I");
|
|
|
|
jfieldID shortcutProbabilityFieldId =
|
|
|
|
env->GetFieldID(languageModelParamClass, "mShortcutProbability", "I");
|
|
|
|
jfieldID isNotAWordFieldId =
|
|
|
|
env->GetFieldID(languageModelParamClass, "mIsNotAWord", "Z");
|
|
|
|
jfieldID isBlacklistedFieldId =
|
|
|
|
env->GetFieldID(languageModelParamClass, "mIsBlacklisted", "Z");
|
|
|
|
env->DeleteLocalRef(languageModelParamClass);
|
|
|
|
|
|
|
|
for (int i = startIndex; i < languageModelParamCount; ++i) {
|
|
|
|
jobject languageModelParam = env->GetObjectArrayElement(languageModelParams, i);
|
|
|
|
// languageModelParam is a set of params for word1; thus, word1 cannot be null. On the
|
|
|
|
// other hand, word0 can be null and then it means the set of params doesn't contain bigram
|
|
|
|
// information.
|
|
|
|
jintArray word0 = static_cast<jintArray>(
|
|
|
|
env->GetObjectField(languageModelParam, word0FieldId));
|
|
|
|
jsize word0Length = word0 ? env->GetArrayLength(word0) : 0;
|
|
|
|
int word0CodePoints[word0Length];
|
|
|
|
if (word0) {
|
|
|
|
env->GetIntArrayRegion(word0, 0, word0Length, word0CodePoints);
|
|
|
|
}
|
|
|
|
jintArray word1 = static_cast<jintArray>(
|
|
|
|
env->GetObjectField(languageModelParam, word1FieldId));
|
|
|
|
jsize word1Length = env->GetArrayLength(word1);
|
|
|
|
int word1CodePoints[word1Length];
|
|
|
|
env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
|
|
|
|
jint unigramProbability = env->GetIntField(languageModelParam, unigramProbabilityFieldId);
|
|
|
|
jint timestamp = env->GetIntField(languageModelParam, timestampFieldId);
|
|
|
|
jboolean isNotAWord = env->GetBooleanField(languageModelParam, isNotAWordFieldId);
|
|
|
|
jboolean isBlacklisted = env->GetBooleanField(languageModelParam, isBlacklistedFieldId);
|
|
|
|
jintArray shortcutTarget = static_cast<jintArray>(
|
|
|
|
env->GetObjectField(languageModelParam, shortcutTargetFieldId));
|
|
|
|
jsize shortcutLength = shortcutTarget ? env->GetArrayLength(shortcutTarget) : 0;
|
|
|
|
int shortcutTargetCodePoints[shortcutLength];
|
|
|
|
if (shortcutTarget) {
|
|
|
|
env->GetIntArrayRegion(shortcutTarget, 0, shortcutLength, shortcutTargetCodePoints);
|
|
|
|
}
|
|
|
|
jint shortcutProbability = env->GetIntField(languageModelParam, shortcutProbabilityFieldId);
|
|
|
|
dictionary->addUnigramWord(word1CodePoints, word1Length, unigramProbability,
|
|
|
|
shortcutTargetCodePoints, shortcutLength, shortcutProbability,
|
|
|
|
isNotAWord, isBlacklisted, timestamp);
|
|
|
|
if (word0) {
|
|
|
|
jint bigramProbability = env->GetIntField(languageModelParam, bigramProbabilityFieldId);
|
|
|
|
dictionary->addBigramWords(word0CodePoints, word0Length, word1CodePoints, word1Length,
|
|
|
|
bigramProbability, timestamp);
|
|
|
|
}
|
|
|
|
if (dictionary->needsToRunGC(true /* mindsBlockByGC */)) {
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
env->DeleteLocalRef(word0);
|
|
|
|
env->DeleteLocalRef(word1);
|
|
|
|
env->DeleteLocalRef(shortcutTarget);
|
|
|
|
env->DeleteLocalRef(languageModelParam);
|
|
|
|
}
|
|
|
|
return languageModelParamCount;
|
|
|
|
}
|
|
|
|
|
2013-09-18 02:18:28 +00:00
|
|
|
static int latinime_BinaryDictionary_calculateProbabilityNative(JNIEnv *env, jclass clazz,
|
|
|
|
jlong dict, jint unigramProbability, jint bigramProbability) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) {
|
|
|
|
return NOT_A_PROBABILITY;
|
|
|
|
}
|
|
|
|
return dictionary->getDictionaryStructurePolicy()->getProbability(unigramProbability,
|
|
|
|
bigramProbability);
|
|
|
|
}
|
|
|
|
|
2013-09-27 14:12:12 +00:00
|
|
|
static jstring latinime_BinaryDictionary_getProperty(JNIEnv *env, jclass clazz, jlong dict,
|
|
|
|
jstring query) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) {
|
|
|
|
return env->NewStringUTF("");
|
|
|
|
}
|
|
|
|
const jsize queryUtf8Length = env->GetStringUTFLength(query);
|
|
|
|
char queryChars[queryUtf8Length + 1];
|
|
|
|
env->GetStringUTFRegion(query, 0, env->GetStringLength(query), queryChars);
|
|
|
|
queryChars[queryUtf8Length] = '\0';
|
|
|
|
static const int GET_PROPERTY_RESULT_LENGTH = 100;
|
|
|
|
char resultChars[GET_PROPERTY_RESULT_LENGTH];
|
|
|
|
resultChars[0] = '\0';
|
2013-12-13 08:09:16 +00:00
|
|
|
dictionary->getProperty(queryChars, queryUtf8Length, resultChars, GET_PROPERTY_RESULT_LENGTH);
|
2013-09-27 14:12:12 +00:00
|
|
|
return env->NewStringUTF(resultChars);
|
|
|
|
}
|
|
|
|
|
2014-02-21 06:09:37 +00:00
|
|
|
static bool latinime_BinaryDictionary_isCorruptedNative(JNIEnv *env, jclass clazz, jlong dict) {
|
|
|
|
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
|
|
|
|
if (!dictionary) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return dictionary->getDictionaryStructurePolicy()->isCorrupted();
|
|
|
|
}
|
|
|
|
|
2013-06-04 10:16:47 +00:00
|
|
|
static const JNINativeMethod sMethods[] = {
|
|
|
|
{
|
|
|
|
const_cast<char *>("openNative"),
|
2013-06-25 05:25:01 +00:00
|
|
|
const_cast<char *>("(Ljava/lang/String;JJZ)J"),
|
2013-06-04 10:16:47 +00:00
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_open)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("closeNative"),
|
|
|
|
const_cast<char *>("(J)V"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_close)
|
|
|
|
},
|
2013-12-13 08:09:16 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("getFormatVersionNative"),
|
|
|
|
const_cast<char *>("(J)I"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getFormatVersion)
|
|
|
|
},
|
2014-02-04 12:39:44 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("getHeaderInfoNative"),
|
|
|
|
const_cast<char *>("(J[I[ILjava/util/ArrayList;Ljava/util/ArrayList;)V"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getHeaderInfo)
|
|
|
|
},
|
2013-09-17 09:07:16 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("flushNative"),
|
|
|
|
const_cast<char *>("(JLjava/lang/String;)V"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_flush)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("needsToRunGCNative"),
|
2013-09-30 04:57:54 +00:00
|
|
|
const_cast<char *>("(JZ)Z"),
|
2013-09-17 09:07:16 +00:00
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_needsToRunGC)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("flushWithGCNative"),
|
|
|
|
const_cast<char *>("(JLjava/lang/String;)V"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_flushWithGC)
|
|
|
|
},
|
2013-06-04 10:16:47 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("getSuggestionsNative"),
|
2014-03-20 09:47:45 +00:00
|
|
|
const_cast<char *>("(JJJ[I[I[I[I[II[I[I[I[I[I[I[I[I)V"),
|
2013-06-04 10:16:47 +00:00
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getSuggestions)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("getProbabilityNative"),
|
|
|
|
const_cast<char *>("(J[I)I"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getProbability)
|
|
|
|
},
|
|
|
|
{
|
2013-09-18 02:18:28 +00:00
|
|
|
const_cast<char *>("getBigramProbabilityNative"),
|
|
|
|
const_cast<char *>("(J[I[I)I"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getBigramProbability)
|
2013-06-04 10:16:47 +00:00
|
|
|
},
|
2013-12-13 08:09:16 +00:00
|
|
|
{
|
2014-01-31 02:06:42 +00:00
|
|
|
const_cast<char *>("getWordPropertyNative"),
|
2014-01-31 11:32:44 +00:00
|
|
|
const_cast<char *>("(J[I[I[Z[ILjava/util/ArrayList;Ljava/util/ArrayList;"
|
|
|
|
"Ljava/util/ArrayList;Ljava/util/ArrayList;)V"),
|
2014-01-31 02:06:42 +00:00
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getWordProperty)
|
2013-12-13 08:09:16 +00:00
|
|
|
},
|
2014-02-03 05:51:58 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("getNextWordNative"),
|
|
|
|
const_cast<char *>("(JI[I)I"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getNextWord)
|
|
|
|
},
|
2013-06-26 03:51:33 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("addUnigramWordNative"),
|
2013-12-13 08:09:16 +00:00
|
|
|
const_cast<char *>("(J[II[IIZZI)V"),
|
2013-06-26 03:51:33 +00:00
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_addUnigramWord)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("addBigramWordsNative"),
|
2013-12-13 08:09:16 +00:00
|
|
|
const_cast<char *>("(J[I[III)V"),
|
2013-06-26 03:51:33 +00:00
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_addBigramWords)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("removeBigramWordsNative"),
|
|
|
|
const_cast<char *>("(J[I[I)V"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_removeBigramWords)
|
2013-09-18 02:18:28 +00:00
|
|
|
},
|
2013-12-13 08:09:16 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("addMultipleDictionaryEntriesNative"),
|
|
|
|
const_cast<char *>(
|
2014-01-15 09:39:36 +00:00
|
|
|
"(J[Lcom/android/inputmethod/latin/utils/LanguageModelParam;I)I"),
|
2013-12-13 08:09:16 +00:00
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_addMultipleDictionaryEntries)
|
|
|
|
},
|
2013-09-18 02:18:28 +00:00
|
|
|
{
|
|
|
|
const_cast<char *>("calculateProbabilityNative"),
|
|
|
|
const_cast<char *>("(JII)I"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_calculateProbabilityNative)
|
2013-09-27 14:12:12 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("getPropertyNative"),
|
|
|
|
const_cast<char *>("(JLjava/lang/String;)Ljava/lang/String;"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_getProperty)
|
2014-02-21 06:09:37 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
const_cast<char *>("isCorruptedNative"),
|
|
|
|
const_cast<char *>("(J)Z"),
|
|
|
|
reinterpret_cast<void *>(latinime_BinaryDictionary_isCorruptedNative)
|
2013-06-04 10:16:47 +00:00
|
|
|
}
|
2009-03-13 22:11:42 +00:00
|
|
|
};
|
|
|
|
|
2011-02-22 08:28:55 +00:00
|
|
|
int register_BinaryDictionary(JNIEnv *env) {
|
2012-07-25 08:51:43 +00:00
|
|
|
const char *const kClassPathName = "com/android/inputmethod/latin/BinaryDictionary";
|
2012-10-08 02:46:14 +00:00
|
|
|
return registerNativeMethods(env, kClassPathName, sMethods, NELEMS(sMethods));
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2011-06-18 04:09:55 +00:00
|
|
|
} // namespace latinime
|