1 /*
2 * Copyright (C) 2013, 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 #include "dictionary/structure/v4/content/shortcut_dict_content.h"
18
19 #include "dictionary/utils/buffer_with_extendable_buffer.h"
20
21 namespace latinime {
22
getShortcutEntryAndAdvancePosition(const int maxCodePointCount,int * const outCodePoint,int * const outCodePointCount,int * const outProbability,bool * const outhasNext,int * const shortcutEntryPos) const23 void ShortcutDictContent::getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
24 int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
25 bool *const outhasNext, int *const shortcutEntryPos) const {
26 const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer();
27 if (*shortcutEntryPos < 0 || *shortcutEntryPos >= shortcutListBuffer->getTailPosition()) {
28 AKLOGE("Invalid shortcut entry position. shortcutEntryPos: %d, bufSize: %d",
29 *shortcutEntryPos, shortcutListBuffer->getTailPosition());
30 ASSERT(false);
31 if (outhasNext) {
32 *outhasNext = false;
33 }
34 if (outCodePointCount) {
35 *outCodePointCount = 0;
36 }
37 return;
38 }
39
40 const int shortcutFlags = shortcutListBuffer->readUintAndAdvancePosition(
41 Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
42 if (outProbability) {
43 *outProbability = shortcutFlags & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK;
44 }
45 if (outhasNext) {
46 *outhasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
47 }
48 if (outCodePoint && outCodePointCount) {
49 shortcutListBuffer->readCodePointsAndAdvancePosition(
50 maxCodePointCount, outCodePoint, outCodePointCount, shortcutEntryPos);
51 }
52 }
53
getShortcutListHeadPos(const int terminalId) const54 int ShortcutDictContent::getShortcutListHeadPos(const int terminalId) const {
55 const SparseTable *const addressLookupTable = getAddressLookupTable();
56 if (!addressLookupTable->contains(terminalId)) {
57 return NOT_A_DICT_POS;
58 }
59 return addressLookupTable->get(terminalId);
60 }
61
runGC(const TerminalPositionLookupTable::TerminalIdMap * const terminalIdMap,const ShortcutDictContent * const originalShortcutDictContent)62 bool ShortcutDictContent::runGC(
63 const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
64 const ShortcutDictContent *const originalShortcutDictContent) {
65 for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
66 it != terminalIdMap->end(); ++it) {
67 const int originalShortcutListPos =
68 originalShortcutDictContent->getShortcutListHeadPos(it->first);
69 if (originalShortcutListPos == NOT_A_DICT_POS) {
70 continue;
71 }
72 const int shortcutListPos = getContentBuffer()->getTailPosition();
73 // Copy shortcut list from original content.
74 if (!copyShortcutListFromDictContent(originalShortcutListPos, originalShortcutDictContent,
75 shortcutListPos)) {
76 AKLOGE("Cannot copy shortcut list during GC. original pos: %d, pos: %d",
77 originalShortcutListPos, shortcutListPos);
78 return false;
79 }
80 // Set shortcut list position to the lookup table.
81 if (!getUpdatableAddressLookupTable()->set(it->second, shortcutListPos)) {
82 AKLOGE("Cannot set shortcut list position. terminal id: %d, pos: %d",
83 it->second, shortcutListPos);
84 return false;
85 }
86 }
87 return true;
88 }
89
createNewShortcutList(const int terminalId)90 bool ShortcutDictContent::createNewShortcutList(const int terminalId) {
91 const int shortcutListListPos = getContentBuffer()->getTailPosition();
92 return getUpdatableAddressLookupTable()->set(terminalId, shortcutListListPos);
93 }
94
copyShortcutList(const int shortcutListPos,const int toPos)95 bool ShortcutDictContent::copyShortcutList(const int shortcutListPos, const int toPos) {
96 return copyShortcutListFromDictContent(shortcutListPos, this, toPos);
97 }
98
copyShortcutListFromDictContent(const int shortcutListPos,const ShortcutDictContent * const sourceShortcutDictContent,const int toPos)99 bool ShortcutDictContent::copyShortcutListFromDictContent(const int shortcutListPos,
100 const ShortcutDictContent *const sourceShortcutDictContent, const int toPos) {
101 bool hasNext = true;
102 int readingPos = shortcutListPos;
103 int writingPos = toPos;
104 int codePoints[MAX_WORD_LENGTH];
105 while (hasNext) {
106 int probability = 0;
107 int codePointCount = 0;
108 sourceShortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH,
109 codePoints, &codePointCount, &probability, &hasNext, &readingPos);
110 if (!writeShortcutEntryAndAdvancePosition(codePoints, codePointCount, probability,
111 hasNext, &writingPos)) {
112 AKLOGE("Cannot write shortcut entry to copy. pos: %d", writingPos);
113 return false;
114 }
115 }
116 return true;
117 }
118
setProbability(const int probability,const int shortcutEntryPos)119 bool ShortcutDictContent::setProbability(const int probability, const int shortcutEntryPos) {
120 BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
121 const int shortcutFlags = shortcutListBuffer->readUint(
122 Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
123 const bool hasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
124 const int shortcutFlagsToWrite = createAndGetShortcutFlags(probability, hasNext);
125 return shortcutListBuffer->writeUint(shortcutFlagsToWrite,
126 Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
127 }
128
writeShortcutEntryAndAdvancePosition(const int * const codePoint,const int codePointCount,const int probability,const bool hasNext,int * const shortcutEntryPos)129 bool ShortcutDictContent::writeShortcutEntryAndAdvancePosition(const int *const codePoint,
130 const int codePointCount, const int probability, const bool hasNext,
131 int *const shortcutEntryPos) {
132 BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
133 const int shortcutFlags = createAndGetShortcutFlags(probability, hasNext);
134 if (!shortcutListBuffer->writeUintAndAdvancePosition(shortcutFlags,
135 Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos)) {
136 AKLOGE("Cannot write shortcut flags. flags; %x, pos: %d", shortcutFlags, *shortcutEntryPos);
137 return false;
138 }
139 if (!shortcutListBuffer->writeCodePointsAndAdvancePosition(codePoint, codePointCount,
140 true /* writesTerminator */, shortcutEntryPos)) {
141 AKLOGE("Cannot write shortcut target code points. pos: %d", *shortcutEntryPos);
142 return false;
143 }
144 return true;
145 }
146
147 // Find a shortcut entry that has specified target and return its position.
findShortcutEntryAndGetPos(const int shortcutListPos,const int * const targetCodePointsToFind,const int codePointCount) const148 int ShortcutDictContent::findShortcutEntryAndGetPos(const int shortcutListPos,
149 const int *const targetCodePointsToFind, const int codePointCount) const {
150 bool hasNext = true;
151 int readingPos = shortcutListPos;
152 int targetCodePoints[MAX_WORD_LENGTH];
153 while (hasNext) {
154 const int entryPos = readingPos;
155 int probability = 0;
156 int targetCodePointCount = 0;
157 getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, targetCodePoints, &targetCodePointCount,
158 &probability, &hasNext, &readingPos);
159 if (targetCodePointCount != codePointCount) {
160 continue;
161 }
162 bool matched = true;
163 for (int i = 0; i < codePointCount; ++i) {
164 if (targetCodePointsToFind[i] != targetCodePoints[i]) {
165 matched = false;
166 break;
167 }
168 }
169 if (matched) {
170 return entryPos;
171 }
172 }
173 return NOT_A_DICT_POS;
174 }
175
createAndGetShortcutFlags(const int probability,const bool hasNext) const176 int ShortcutDictContent::createAndGetShortcutFlags(const int probability,
177 const bool hasNext) const {
178 return (probability & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK)
179 | (hasNext ? Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK : 0);
180 }
181
182 } // namespace latinime
183