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