dictionary.cpp revision d4fcf1dbc5e795c10aae60e51b6aa3f78c8d8a3a
1/*
2 * Copyright (C) 2009, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "LatinIME: dictionary.cpp"
18
19#include "suggest/core/dictionary/dictionary.h"
20
21#include <stdint.h>
22
23#include "defines.h"
24#include "suggest/core/dictionary/bigram_dictionary.h"
25#include "suggest/core/policy/dictionary_header_structure_policy.h"
26#include "suggest/core/session/dic_traverse_session.h"
27#include "suggest/core/suggest.h"
28#include "suggest/core/suggest_options.h"
29#include "suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h"
30#include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
31#include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
32#include "utils/log_utils.h"
33
34namespace latinime {
35
36Dictionary::Dictionary(JNIEnv *env, void *dict, int dictSize, int mmapFd,
37        int dictBufOffset, bool isUpdatable)
38        : mBinaryDictionaryInfo(static_cast<const uint8_t *>(dict), dictSize, mmapFd,
39                dictBufOffset, isUpdatable),
40          mDictionaryStructureWithBufferPolicy(DictionaryStructureWithBufferPolicyFactory
41                  ::newDictionaryStructureWithBufferPolicy(
42                          static_cast<const uint8_t *>(dict), dictSize)),
43          mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy)),
44          mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
45          mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
46    logDictionaryInfo(env);
47}
48
49Dictionary::~Dictionary() {
50    delete mBigramDictionary;
51    delete mGestureSuggest;
52    delete mTypingSuggest;
53    delete mDictionaryStructureWithBufferPolicy;
54}
55
56int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
57        int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
58        int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint,
59        const SuggestOptions *const suggestOptions, int *outWords, int *frequencies,
60        int *spaceIndices, int *outputTypes) const {
61    int result = 0;
62    if (suggestOptions->isGesture()) {
63        DicTraverseSession::initSessionInstance(
64                traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
65        result = mGestureSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
66                ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, outWords,
67                frequencies, spaceIndices, outputTypes);
68        if (DEBUG_DICT) {
69            DUMP_RESULT(outWords, frequencies);
70        }
71        return result;
72    } else {
73        DicTraverseSession::initSessionInstance(
74                traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
75        result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
76                ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
77                outWords, frequencies, spaceIndices, outputTypes);
78        if (DEBUG_DICT) {
79            DUMP_RESULT(outWords, frequencies);
80        }
81        return result;
82    }
83}
84
85int Dictionary::getBigrams(const int *word, int length, int *outWords, int *frequencies,
86        int *outputTypes) const {
87    if (length <= 0) return 0;
88    return mBigramDictionary->getPredictions(word, length, outWords, frequencies, outputTypes);
89}
90
91int Dictionary::getProbability(const int *word, int length) const {
92    int pos = getDictionaryStructurePolicy()->getTerminalNodePositionOfWord(word, length,
93            false /* forceLowerCaseSearch */);
94    if (NOT_A_VALID_WORD_POS == pos) {
95        return NOT_A_PROBABILITY;
96    }
97    return getDictionaryStructurePolicy()->getUnigramProbability(pos);
98}
99
100bool Dictionary::isValidBigram(const int *word0, int length0, const int *word1, int length1) const {
101    return mBigramDictionary->isValidBigram(word0, length0, word1, length1);
102}
103
104void Dictionary::addUnigramWord(const int *const word, const int length, const int probability) {
105    if (!mBinaryDictionaryInfo.isDynamicallyUpdatable()) {
106        // This method should not be called for non-updatable dictionary.
107        AKLOGI("Warning: Dictionary::addUnigramWord() is called for non-updatable dictionary.");
108        return;
109    }
110    mDictionaryStructureWithBufferPolicy->addUnigramWord(word, length, probability);
111}
112
113void Dictionary::addBigramWords(const int *const word0, const int length0, const int *const word1,
114        const int length1, const int probability) {
115    if (!mBinaryDictionaryInfo.isDynamicallyUpdatable()) {
116        // This method should not be called for non-updatable dictionary.
117        AKLOGI("Warning: Dictionary::addBigramWords() is called for non-updatable dictionary.");
118        return;
119    }
120    mDictionaryStructureWithBufferPolicy->addBigramWords(word0, length0, word1, length1,
121            probability);
122}
123
124void Dictionary::removeBigramWords(const int *const word0, const int length0,
125        const int *const word1, const int length1) {
126    if (!mBinaryDictionaryInfo.isDynamicallyUpdatable()) {
127        // This method should not be called for non-updatable dictionary.
128        AKLOGI("Warning: Dictionary::removeBigramWords() is called for non-updatable dictionary.");
129        return;
130    }
131    mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1);
132}
133
134void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
135    const int BUFFER_SIZE = 16;
136    int dictionaryIdCodePointBuffer[BUFFER_SIZE];
137    int versionStringCodePointBuffer[BUFFER_SIZE];
138    int dateStringCodePointBuffer[BUFFER_SIZE];
139    const DictionaryHeaderStructurePolicy *const headerPolicy =
140            getDictionaryStructurePolicy()->getHeaderStructurePolicy();
141    headerPolicy->readHeaderValueOrQuestionMark("dictionary", dictionaryIdCodePointBuffer,
142            BUFFER_SIZE);
143    headerPolicy->readHeaderValueOrQuestionMark("version", versionStringCodePointBuffer,
144            BUFFER_SIZE);
145    headerPolicy->readHeaderValueOrQuestionMark("date", dateStringCodePointBuffer, BUFFER_SIZE);
146
147    char dictionaryIdCharBuffer[BUFFER_SIZE];
148    char versionStringCharBuffer[BUFFER_SIZE];
149    char dateStringCharBuffer[BUFFER_SIZE];
150    intArrayToCharArray(dictionaryIdCodePointBuffer, BUFFER_SIZE,
151            dictionaryIdCharBuffer, BUFFER_SIZE);
152    intArrayToCharArray(versionStringCodePointBuffer, BUFFER_SIZE,
153            versionStringCharBuffer, BUFFER_SIZE);
154    intArrayToCharArray(dateStringCodePointBuffer, BUFFER_SIZE,
155            dateStringCharBuffer, BUFFER_SIZE);
156
157    LogUtils::logToJava(env,
158            "Dictionary info: dictionary = %s ; version = %s ; date = %s ; filesize = %i",
159            dictionaryIdCharBuffer, versionStringCharBuffer, dateStringCharBuffer,
160            mBinaryDictionaryInfo.getDictSize());
161}
162
163} // namespace latinime
164