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
26namespace latinime {
27
28// Class to have information to be output. This can contain previous words when the suggestion
29// is a multi-word suggestion.
30class DicNodeStateOutput {
31 public:
32    DicNodeStateOutput()
33            : mOutputtedCodePointCount(0), mCurrentWordStart(0), mPrevWordCount(0),
34              mPrevWordsLength(0), mPrevWordStart(0), mSecondWordFirstInputIndex(NOT_AN_INDEX) {}
35
36    ~DicNodeStateOutput() {}
37
38    // Init for root
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.
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
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
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
93    int getCurrentWordCodePointAt(const int index) const {
94        return mOutputCodePoints[mCurrentWordStart + index];
95    }
96
97    const int *getCodePointBuf() const {
98        return mOutputCodePoints;
99    }
100
101    void setSecondWordFirstInputIndex(const int inputIndex) {
102        mSecondWordFirstInputIndex = inputIndex;
103    }
104
105    int getSecondWordFirstInputIndex() const {
106        return mSecondWordFirstInputIndex;
107    }
108
109    // TODO: remove
110    int16_t getPrevWordsLength() const {
111        return mPrevWordsLength;
112    }
113
114    int16_t getPrevWordCount() const {
115        return mPrevWordCount;
116    }
117
118    int16_t getPrevWordStart() const {
119        return mPrevWordStart;
120    }
121
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