dic_traverse_session.h revision cafab169cdb21244c82b99c09983c98066113d87
1/*
2 * Copyright (C) 2012 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#ifndef LATINIME_DIC_TRAVERSE_SESSION_H
18#define LATINIME_DIC_TRAVERSE_SESSION_H
19
20#include <vector>
21
22#include "defines.h"
23#include "jni.h"
24#include "suggest/core/dicnode/dic_nodes_cache.h"
25#include "suggest/core/dictionary/multi_bigram_map.h"
26#include "suggest/core/layout/proximity_info_state.h"
27
28namespace latinime {
29
30class Dictionary;
31class DictionaryStructureWithBufferPolicy;
32class ProximityInfo;
33class SuggestOptions;
34
35class DicTraverseSession {
36 public:
37
38    // A factory method for DicTraverseSession
39    static AK_FORCE_INLINE void *getSessionInstance(JNIEnv *env, jstring localeStr,
40            jlong dictSize) {
41        // To deal with the trade-off between accuracy and memory space, large cache is used for
42        // dictionaries larger that the threshold
43        return new DicTraverseSession(env, localeStr,
44                dictSize >= DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION);
45    }
46
47    static AK_FORCE_INLINE void initSessionInstance(DicTraverseSession *traverseSession,
48            const Dictionary *const dictionary, const int *prevWord, const int prevWordLength,
49            const SuggestOptions *const suggestOptions) {
50        if (traverseSession) {
51            DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
52            tSession->init(dictionary, prevWord, prevWordLength, suggestOptions);
53        }
54    }
55
56    static AK_FORCE_INLINE void releaseSessionInstance(DicTraverseSession *traverseSession) {
57        delete traverseSession;
58    }
59
60    AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache)
61            : mPrevWordPtNodePos(NOT_A_DICT_POS), mProximityInfo(nullptr),
62              mDictionary(nullptr), mSuggestOptions(nullptr), mDicNodesCache(usesLargeCache),
63              mMultiBigramMap(), mInputSize(0), mMaxPointerCount(1),
64              mMultiWordCostMultiplier(1.0f) {
65        // NOTE: mProximityInfoStates is an array of instances.
66        // No need to initialize it explicitly here.
67    }
68
69    // Non virtual inline destructor -- never inherit this class
70    AK_FORCE_INLINE ~DicTraverseSession() {}
71
72    void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength,
73            const SuggestOptions *const suggestOptions);
74    // TODO: Remove and merge into init
75    void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
76            const int inputSize, const int *const inputXs, const int *const inputYs,
77            const int *const times, const int *const pointerIds, const float maxSpatialDistance,
78            const int maxPointerCount);
79    void resetCache(const int thresholdForNextActiveDicNodes, const int maxWords);
80
81    const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const;
82
83    //--------------------
84    // getters and setters
85    //--------------------
86    const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
87    const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
88    int getPrevWordPtNodePos() const { return mPrevWordPtNodePos; }
89    // TODO: REMOVE
90    void setPrevWordPtNodePos(const int ptNodePos) { mPrevWordPtNodePos = ptNodePos; }
91    DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
92    MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; }
93    const ProximityInfoState *getProximityInfoState(int id) const {
94        return &mProximityInfoStates[id];
95    }
96    int getInputSize() const { return mInputSize; }
97
98    bool isOnlyOnePointerUsed(int *pointerId) const {
99        // Not in the dictionary word
100        int usedPointerCount = 0;
101        int usedPointerId = 0;
102        for (int i = 0; i < mMaxPointerCount; ++i) {
103            if (mProximityInfoStates[i].isUsed()) {
104                ++usedPointerCount;
105                usedPointerId = i;
106            }
107        }
108        if (usedPointerCount != 1) {
109            return false;
110        }
111        if (pointerId) {
112            *pointerId = usedPointerId;
113        }
114        return true;
115    }
116
117    ProximityType getProximityTypeG(const DicNode *const dicNode, const int childCodePoint) const {
118        ProximityType proximityType = UNRELATED_CHAR;
119        for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
120            if (!mProximityInfoStates[i].isUsed()) {
121                continue;
122            }
123            const int pointerId = dicNode->getInputIndex(i);
124            proximityType = mProximityInfoStates[i].getProximityTypeG(pointerId, childCodePoint);
125            ASSERT(proximityType == UNRELATED_CHAR || proximityType == MATCH_CHAR);
126            // TODO: Make this more generic
127            // Currently we assume there are only two types here -- UNRELATED_CHAR
128            // and MATCH_CHAR
129            if (proximityType != UNRELATED_CHAR) {
130                return proximityType;
131            }
132        }
133        return proximityType;
134    }
135
136    AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const {
137        return mDicNodesCache.isCacheBorderForTyping(inputSize);
138    }
139
140    /**
141     * Returns whether or not it is possible to continue suggestion from the previous search.
142     */
143    // TODO: Remove. No need to check once the session is fully implemented.
144    bool isContinuousSuggestionPossible() const {
145        if (!mDicNodesCache.hasCachedDicNodesForContinuousSuggestion()) {
146            return false;
147        }
148        ASSERT(mMaxPointerCount <= MAX_POINTER_COUNT_G);
149        for (int i = 0; i < mMaxPointerCount; ++i) {
150            const ProximityInfoState *const pInfoState = getProximityInfoState(i);
151            // If a proximity info state is not continuous suggestion possible,
152            // do not continue searching.
153            if (pInfoState->isUsed() && !pInfoState->isContinuousSuggestionPossible()) {
154                return false;
155            }
156        }
157        return true;
158    }
159
160    bool isTouchPositionCorrectionEnabled() const {
161        return mProximityInfoStates[0].touchPositionCorrectionEnabled();
162    }
163
164    float getMultiWordCostMultiplier() const {
165        return mMultiWordCostMultiplier;
166    }
167
168 private:
169    DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
170    // threshold to start caching
171    static const int CACHE_START_INPUT_LENGTH_THRESHOLD;
172    static const int DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION;
173    void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs,
174            const int *const inputYs, const int *const times, const int *const pointerIds,
175            const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
176
177    int mPrevWordPtNodePos;
178    const ProximityInfo *mProximityInfo;
179    const Dictionary *mDictionary;
180    const SuggestOptions *mSuggestOptions;
181
182    DicNodesCache mDicNodesCache;
183    // Temporary cache for bigram frequencies
184    MultiBigramMap mMultiBigramMap;
185    ProximityInfoState mProximityInfoStates[MAX_POINTER_COUNT_G];
186
187    int mInputSize;
188    int mMaxPointerCount;
189
190    /////////////////////////////////
191    // Configuration per dictionary
192    float mMultiWordCostMultiplier;
193
194};
195} // namespace latinime
196#endif // LATINIME_DIC_TRAVERSE_SESSION_H
197