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