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_NODES_CACHE_H 18 #define LATINIME_DIC_NODES_CACHE_H 19 20 #include <stdint.h> 21 22 #include "defines.h" 23 #include "dic_node_priority_queue.h" 24 25 #define INITIAL_QUEUE_ID_ACTIVE 0 26 #define INITIAL_QUEUE_ID_NEXT_ACTIVE 1 27 #define INITIAL_QUEUE_ID_TERMINAL 2 28 #define INITIAL_QUEUE_ID_CACHE_FOR_CONTINUOUS_SUGGESTION 3 29 #define PRIORITY_QUEUES_SIZE 4 30 31 namespace latinime { 32 33 class DicNode; 34 35 /** 36 * Class for controlling dicNode search priority queue and lexicon trie traversal. 37 */ 38 class DicNodesCache { 39 public: 40 AK_FORCE_INLINE DicNodesCache() 41 : mActiveDicNodes(&mDicNodePriorityQueues[INITIAL_QUEUE_ID_ACTIVE]), 42 mNextActiveDicNodes(&mDicNodePriorityQueues[INITIAL_QUEUE_ID_NEXT_ACTIVE]), 43 mTerminalDicNodes(&mDicNodePriorityQueues[INITIAL_QUEUE_ID_TERMINAL]), 44 mCachedDicNodesForContinuousSuggestion( 45 &mDicNodePriorityQueues[INITIAL_QUEUE_ID_CACHE_FOR_CONTINUOUS_SUGGESTION]), 46 mInputIndex(0), mLastCachedInputIndex(0) { 47 } 48 49 AK_FORCE_INLINE virtual ~DicNodesCache() {} 50 51 AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) { 52 mInputIndex = 0; 53 mLastCachedInputIndex = 0; 54 mActiveDicNodes->reset(); 55 mNextActiveDicNodes->clearAndResize(nextActiveSize); 56 mTerminalDicNodes->clearAndResize(terminalSize); 57 mCachedDicNodesForContinuousSuggestion->reset(); 58 } 59 60 AK_FORCE_INLINE void continueSearch() { 61 resetTemporaryCaches(); 62 restoreActiveDicNodesFromCache(); 63 } 64 65 AK_FORCE_INLINE void advanceActiveDicNodes() { 66 if (DEBUG_DICT) { 67 AKLOGI("Advance active %d nodes.", mNextActiveDicNodes->getSize()); 68 } 69 if (DEBUG_DICT_FULL) { 70 mNextActiveDicNodes->dump(); 71 } 72 mNextActiveDicNodes = 73 moveNodesAndReturnReusableEmptyQueue(mNextActiveDicNodes, &mActiveDicNodes); 74 } 75 76 DicNode *setCommitPoint(int commitPoint); 77 78 int activeSize() const { return mActiveDicNodes->getSize(); } 79 int terminalSize() const { return mTerminalDicNodes->getSize(); } 80 bool isLookAheadCorrectionInputIndex(const int inputIndex) const { 81 return inputIndex == mInputIndex - 1; 82 } 83 void advanceInputIndex(const int inputSize) { 84 if (mInputIndex < inputSize) { 85 mInputIndex++; 86 } 87 } 88 89 AK_FORCE_INLINE void copyPushTerminal(DicNode *dicNode) { 90 mTerminalDicNodes->copyPush(dicNode); 91 } 92 93 AK_FORCE_INLINE void copyPushActive(DicNode *dicNode) { 94 mActiveDicNodes->copyPush(dicNode); 95 } 96 97 AK_FORCE_INLINE bool copyPushContinue(DicNode *dicNode) { 98 return mCachedDicNodesForContinuousSuggestion->copyPush(dicNode); 99 } 100 101 AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) { 102 DicNode *pushedDicNode = mNextActiveDicNodes->copyPush(dicNode); 103 if (!pushedDicNode) { 104 if (dicNode->isCached()) { 105 dicNode->remove(); 106 } 107 // We simply drop any dic node that was not cached, ignoring the slim chance 108 // that one of its children represents what the user really wanted. 109 } 110 } 111 112 void popTerminal(DicNode *dest) { 113 mTerminalDicNodes->copyPop(dest); 114 } 115 116 void popActive(DicNode *dest) { 117 mActiveDicNodes->copyPop(dest); 118 } 119 120 bool hasCachedDicNodesForContinuousSuggestion() const { 121 return mCachedDicNodesForContinuousSuggestion 122 && mCachedDicNodesForContinuousSuggestion->getSize() > 0; 123 } 124 125 AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const { 126 // TODO: Move this variable to header 127 static const int CACHE_BACK_LENGTH = 3; 128 const int cacheInputIndex = inputSize - CACHE_BACK_LENGTH; 129 const bool shouldCache = (cacheInputIndex == mInputIndex) 130 && (cacheInputIndex != mLastCachedInputIndex); 131 return shouldCache; 132 } 133 134 AK_FORCE_INLINE void updateLastCachedInputIndex() { 135 mLastCachedInputIndex = mInputIndex; 136 } 137 138 private: 139 DISALLOW_COPY_AND_ASSIGN(DicNodesCache); 140 141 AK_FORCE_INLINE void restoreActiveDicNodesFromCache() { 142 if (DEBUG_DICT) { 143 AKLOGI("Restore %d nodes. inputIndex = %d.", 144 mCachedDicNodesForContinuousSuggestion->getSize(), mLastCachedInputIndex); 145 } 146 if (DEBUG_DICT_FULL || DEBUG_CACHE) { 147 mCachedDicNodesForContinuousSuggestion->dump(); 148 } 149 mInputIndex = mLastCachedInputIndex; 150 mCachedDicNodesForContinuousSuggestion = 151 moveNodesAndReturnReusableEmptyQueue( 152 mCachedDicNodesForContinuousSuggestion, &mActiveDicNodes); 153 } 154 155 AK_FORCE_INLINE static DicNodePriorityQueue *moveNodesAndReturnReusableEmptyQueue( 156 DicNodePriorityQueue *src, DicNodePriorityQueue **dest) { 157 const int srcMaxSize = src->getMaxSize(); 158 const int destMaxSize = (*dest)->getMaxSize(); 159 DicNodePriorityQueue *tmp = *dest; 160 *dest = src; 161 (*dest)->setMaxSize(destMaxSize); 162 tmp->clearAndResize(srcMaxSize); 163 return tmp; 164 } 165 166 AK_FORCE_INLINE void resetTemporaryCaches() { 167 mActiveDicNodes->clear(); 168 mNextActiveDicNodes->clear(); 169 mTerminalDicNodes->clear(); 170 } 171 172 DicNodePriorityQueue mDicNodePriorityQueues[PRIORITY_QUEUES_SIZE]; 173 // Active dicNodes currently being expanded. 174 DicNodePriorityQueue *mActiveDicNodes; 175 // Next dicNodes to be expanded. 176 DicNodePriorityQueue *mNextActiveDicNodes; 177 // Current top terminal dicNodes. 178 DicNodePriorityQueue *mTerminalDicNodes; 179 // Cached dicNodes used for continuous suggestion. 180 DicNodePriorityQueue *mCachedDicNodesForContinuousSuggestion; 181 int mInputIndex; 182 int mLastCachedInputIndex; 183 }; 184 } // namespace latinime 185 #endif // LATINIME_DIC_NODES_CACHE_H 186