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_PREVWORD_H
18#define LATINIME_DIC_NODE_STATE_PREVWORD_H
19
20#include <cstring> // for memset()
21#include <stdint.h>
22
23#include "defines.h"
24#include "dic_node_utils.h"
25
26namespace latinime {
27
28class DicNodeStatePrevWord {
29 public:
30    AK_FORCE_INLINE DicNodeStatePrevWord()
31            : mPrevWordCount(0), mPrevWordLength(0), mPrevWordStart(0), mPrevWordProbability(0),
32              mPrevWordNodePos(0) {
33        memset(mPrevWord, 0, sizeof(mPrevWord));
34        memset(mPrevSpacePositions, 0, sizeof(mPrevSpacePositions));
35    }
36
37    virtual ~DicNodeStatePrevWord() {}
38
39    void init() {
40        mPrevWordLength = 0;
41        mPrevWordCount = 0;
42        mPrevWordStart = 0;
43        mPrevWordProbability = -1;
44        mPrevWordNodePos = NOT_VALID_WORD;
45        memset(mPrevSpacePositions, 0, sizeof(mPrevSpacePositions));
46    }
47
48    void init(const int prevWordNodePos) {
49        mPrevWordLength = 0;
50        mPrevWordCount = 0;
51        mPrevWordStart = 0;
52        mPrevWordProbability = -1;
53        mPrevWordNodePos = prevWordNodePos;
54        memset(mPrevSpacePositions, 0, sizeof(mPrevSpacePositions));
55    }
56
57    // Init by copy
58    AK_FORCE_INLINE void init(const DicNodeStatePrevWord *const prevWord) {
59        mPrevWordLength = prevWord->mPrevWordLength;
60        mPrevWordCount = prevWord->mPrevWordCount;
61        mPrevWordStart = prevWord->mPrevWordStart;
62        mPrevWordProbability = prevWord->mPrevWordProbability;
63        mPrevWordNodePos = prevWord->mPrevWordNodePos;
64        memcpy(mPrevWord, prevWord->mPrevWord, prevWord->mPrevWordLength * sizeof(mPrevWord[0]));
65        memcpy(mPrevSpacePositions, prevWord->mPrevSpacePositions, sizeof(mPrevSpacePositions));
66    }
67
68    void init(const int16_t prevWordCount, const int16_t prevWordProbability,
69            const int prevWordNodePos, const int *const src0, const int16_t length0,
70            const int *const src1, const int16_t length1, const int *const prevSpacePositions,
71            const int lastInputIndex) {
72        mPrevWordCount = prevWordCount;
73        mPrevWordProbability = prevWordProbability;
74        mPrevWordNodePos = prevWordNodePos;
75        const int twoWordsLen =
76                DicNodeUtils::appendTwoWords(src0, length0, src1, length1, mPrevWord);
77        mPrevWord[twoWordsLen] = KEYCODE_SPACE;
78        mPrevWordStart = length0;
79        mPrevWordLength = static_cast<int16_t>(twoWordsLen + 1);
80        memcpy(mPrevSpacePositions, prevSpacePositions, sizeof(mPrevSpacePositions));
81        mPrevSpacePositions[mPrevWordCount - 1] = lastInputIndex;
82    }
83
84    void truncate(const int offset) {
85        // TODO: memmove
86        if (mPrevWordLength < offset) {
87            memset(mPrevWord, 0, sizeof(mPrevWord));
88            mPrevWordLength = 0;
89            return;
90        }
91        const int newPrevWordLength = mPrevWordLength - offset;
92        memmove(mPrevWord, &mPrevWord[offset], newPrevWordLength * sizeof(mPrevWord[0]));
93        mPrevWordLength = newPrevWordLength;
94    }
95
96    void outputSpacePositions(int *spaceIndices) const {
97        // Convert uint16_t to int
98        for (int i = 0; i < MAX_RESULTS; i++) {
99            spaceIndices[i] = mPrevSpacePositions[i];
100        }
101    }
102
103    // TODO: remove
104    int16_t getPrevWordLength() const {
105        return mPrevWordLength;
106    }
107
108    int16_t getPrevWordCount() const {
109        return mPrevWordCount;
110    }
111
112    int16_t getPrevWordStart() const {
113        return mPrevWordStart;
114    }
115
116    int16_t getPrevWordProbability() const {
117        return mPrevWordProbability;
118    }
119
120    int getPrevWordNodePos() const {
121        return mPrevWordNodePos;
122    }
123
124    int getPrevWordCodePointAt(const int id) const {
125        return mPrevWord[id];
126    }
127
128    bool startsWith(const DicNodeStatePrevWord *const prefix, const int prefixLen) const {
129        if (prefixLen > mPrevWordLength) {
130            return false;
131        }
132        for (int i = 0; i < prefixLen; ++i) {
133            if (mPrevWord[i] != prefix->mPrevWord[i]) {
134                return false;
135            }
136        }
137        return true;
138    }
139
140    // TODO: Move to private
141    int mPrevWord[MAX_WORD_LENGTH];
142    // TODO: Move to private
143    int mPrevSpacePositions[MAX_RESULTS];
144
145 private:
146    // Caution!!!
147    // Use a default copy constructor and an assign operator because shallow copies are ok
148    // for this class
149    int16_t mPrevWordCount;
150    int16_t mPrevWordLength;
151    int16_t mPrevWordStart;
152    int16_t mPrevWordProbability;
153    int mPrevWordNodePos;
154};
155} // namespace latinime
156#endif // LATINIME_DIC_NODE_STATE_PREVWORD_H
157