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_NODE_STATE_OUTPUT_H
18 #define LATINIME_DIC_NODE_STATE_OUTPUT_H
19 
20 #include <algorithm>
21 #include <cstdint>
22 #include <cstring> // for memmove()
23 
24 #include "defines.h"
25 
26 namespace latinime {
27 
28 // Class to have information to be output. This can contain previous words when the suggestion
29 // is a multi-word suggestion.
30 class DicNodeStateOutput {
31  public:
DicNodeStateOutput()32     DicNodeStateOutput()
33             : mOutputtedCodePointCount(0), mCurrentWordStart(0), mPrevWordCount(0),
34               mPrevWordsLength(0), mPrevWordStart(0), mSecondWordFirstInputIndex(NOT_AN_INDEX) {}
35 
~DicNodeStateOutput()36     ~DicNodeStateOutput() {}
37 
38     // Init for root
init()39     void init() {
40         mOutputtedCodePointCount = 0;
41         mCurrentWordStart = 0;
42         mOutputCodePoints[0] = 0;
43         mPrevWordCount = 0;
44         mPrevWordsLength = 0;
45         mPrevWordStart = 0;
46         mSecondWordFirstInputIndex = NOT_AN_INDEX;
47     }
48 
49     // Init for next word.
init(const DicNodeStateOutput * const stateOutput)50     void init(const DicNodeStateOutput *const stateOutput) {
51         mOutputtedCodePointCount = stateOutput->mOutputtedCodePointCount + 1;
52         memmove(mOutputCodePoints, stateOutput->mOutputCodePoints,
53                 stateOutput->mOutputtedCodePointCount * sizeof(mOutputCodePoints[0]));
54         mOutputCodePoints[stateOutput->mOutputtedCodePointCount] = KEYCODE_SPACE;
55         mCurrentWordStart = stateOutput->mOutputtedCodePointCount + 1;
56         mPrevWordCount = std::min(static_cast<int16_t>(stateOutput->mPrevWordCount + 1),
57                 static_cast<int16_t>(MAX_RESULTS));
58         mPrevWordsLength = stateOutput->mOutputtedCodePointCount + 1;
59         mPrevWordStart = stateOutput->mCurrentWordStart;
60         mSecondWordFirstInputIndex = stateOutput->mSecondWordFirstInputIndex;
61     }
62 
initByCopy(const DicNodeStateOutput * const stateOutput)63     void initByCopy(const DicNodeStateOutput *const stateOutput) {
64         memmove(mOutputCodePoints, stateOutput->mOutputCodePoints,
65                 stateOutput->mOutputtedCodePointCount * sizeof(mOutputCodePoints[0]));
66         mOutputtedCodePointCount = stateOutput->mOutputtedCodePointCount;
67         if (mOutputtedCodePointCount < MAX_WORD_LENGTH) {
68             mOutputCodePoints[mOutputtedCodePointCount] = 0;
69         }
70         mCurrentWordStart = stateOutput->mCurrentWordStart;
71         mPrevWordCount = stateOutput->mPrevWordCount;
72         mPrevWordsLength = stateOutput->mPrevWordsLength;
73         mPrevWordStart = stateOutput->mPrevWordStart;
74         mSecondWordFirstInputIndex = stateOutput->mSecondWordFirstInputIndex;
75     }
76 
addMergedNodeCodePoints(const uint16_t mergedNodeCodePointCount,const int * const mergedNodeCodePoints)77     void addMergedNodeCodePoints(const uint16_t mergedNodeCodePointCount,
78             const int *const mergedNodeCodePoints) {
79         if (mergedNodeCodePoints) {
80             const int additionalCodePointCount = std::min(
81                     static_cast<int>(mergedNodeCodePointCount),
82                     MAX_WORD_LENGTH - mOutputtedCodePointCount);
83             memmove(&mOutputCodePoints[mOutputtedCodePointCount], mergedNodeCodePoints,
84                     additionalCodePointCount * sizeof(mOutputCodePoints[0]));
85             mOutputtedCodePointCount = static_cast<uint16_t>(
86                     mOutputtedCodePointCount + additionalCodePointCount);
87             if (mOutputtedCodePointCount < MAX_WORD_LENGTH) {
88                 mOutputCodePoints[mOutputtedCodePointCount] = 0;
89             }
90         }
91     }
92 
getCurrentWordCodePointAt(const int index)93     int getCurrentWordCodePointAt(const int index) const {
94         return mOutputCodePoints[mCurrentWordStart + index];
95     }
96 
getCodePointBuf()97     const int *getCodePointBuf() const {
98         return mOutputCodePoints;
99     }
100 
setSecondWordFirstInputIndex(const int inputIndex)101     void setSecondWordFirstInputIndex(const int inputIndex) {
102         mSecondWordFirstInputIndex = inputIndex;
103     }
104 
getSecondWordFirstInputIndex()105     int getSecondWordFirstInputIndex() const {
106         return mSecondWordFirstInputIndex;
107     }
108 
109     // TODO: remove
getPrevWordsLength()110     int16_t getPrevWordsLength() const {
111         return mPrevWordsLength;
112     }
113 
getPrevWordCount()114     int16_t getPrevWordCount() const {
115         return mPrevWordCount;
116     }
117 
getPrevWordStart()118     int16_t getPrevWordStart() const {
119         return mPrevWordStart;
120     }
121 
getOutputCodePointAt(const int id)122     int getOutputCodePointAt(const int id) const {
123         return mOutputCodePoints[id];
124     }
125 
126  private:
127     DISALLOW_COPY_AND_ASSIGN(DicNodeStateOutput);
128 
129     // When the DicNode represents "this is a pen":
130     // mOutputtedCodePointCount is 13, which is total code point count of "this is a pen" including
131     // spaces.
132     // mCurrentWordStart indicates the head of "pen", thus it is 10.
133     // This contains 3 previous words, "this", "is" and "a"; thus, mPrevWordCount is 3.
134     // mPrevWordsLength is length of "this is a ", which is 10.
135     // mPrevWordStart is the start index of "a"; thus, it is 8.
136     // mSecondWordFirstInputIndex is the first input index of "is".
137 
138     uint16_t mOutputtedCodePointCount;
139     int mOutputCodePoints[MAX_WORD_LENGTH];
140     int16_t mCurrentWordStart;
141     // Previous word count in mOutputCodePoints.
142     int16_t mPrevWordCount;
143     // Total length of previous words in mOutputCodePoints. This is being used by the algorithm
144     // that may want to look at the previous word information.
145     int16_t mPrevWordsLength;
146     // Start index of the previous word in mOutputCodePoints. This is being used for auto commit.
147     int16_t mPrevWordStart;
148     int mSecondWordFirstInputIndex;
149 };
150 } // namespace latinime
151 #endif // LATINIME_DIC_NODE_STATE_OUTPUT_H
152