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/terminal_position_lookup_table.h"
18
19 #include "dictionary/utils/buffer_with_extendable_buffer.h"
20
21 namespace latinime {
22
getTerminalPtNodePosition(const int terminalId) const23 int TerminalPositionLookupTable::getTerminalPtNodePosition(const int terminalId) const {
24 if (terminalId < 0 || terminalId >= mSize) {
25 return NOT_A_DICT_POS;
26 }
27 const int terminalPos = getBuffer()->readUint(
28 Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
29 return (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) ?
30 NOT_A_DICT_POS : terminalPos;
31 }
32
setTerminalPtNodePosition(const int terminalId,const int terminalPtNodePos)33 bool TerminalPositionLookupTable::setTerminalPtNodePosition(
34 const int terminalId, const int terminalPtNodePos) {
35 if (terminalId < 0) {
36 return false;
37 }
38 while (terminalId >= mSize) {
39 // Write new entry.
40 if (!getWritableBuffer()->writeUint(Ver4DictConstants::NOT_A_TERMINAL_ADDRESS,
41 Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(mSize))) {
42 return false;
43 }
44 mSize++;
45 }
46 const int terminalPos = (terminalPtNodePos != NOT_A_DICT_POS) ?
47 terminalPtNodePos : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
48 return getWritableBuffer()->writeUint(terminalPos,
49 Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
50 }
51
flushToFile(FILE * const file) const52 bool TerminalPositionLookupTable::flushToFile(FILE *const file) const {
53 // If the used buffer size is smaller than the actual buffer size, regenerate the lookup
54 // table and write the new table to the file.
55 if (getEntryPos(mSize) < getBuffer()->getTailPosition()) {
56 TerminalPositionLookupTable lookupTableToWrite;
57 for (int i = 0; i < mSize; ++i) {
58 const int terminalPtNodePosition = getTerminalPtNodePosition(i);
59 if (!lookupTableToWrite.setTerminalPtNodePosition(i, terminalPtNodePosition)) {
60 AKLOGE("Cannot set terminal position to lookupTableToWrite."
61 " terminalId: %d, position: %d", i, terminalPtNodePosition);
62 return false;
63 }
64 }
65 return lookupTableToWrite.flush(file);
66 } else {
67 // We can simply use this lookup table because the buffer size has not been
68 // changed.
69 return flush(file);
70 }
71 }
72
runGCTerminalIds(TerminalIdMap * const terminalIdMap)73 bool TerminalPositionLookupTable::runGCTerminalIds(TerminalIdMap *const terminalIdMap) {
74 int removedEntryCount = 0;
75 int nextNewTerminalId = 0;
76 for (int i = 0; i < mSize; ++i) {
77 const int terminalPos = getBuffer()->readUint(
78 Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(i));
79 if (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) {
80 // This entry is a garbage.
81 removedEntryCount++;
82 } else {
83 // Give a new terminal id to the entry.
84 if (!getWritableBuffer()->writeUint(terminalPos,
85 Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE,
86 getEntryPos(nextNewTerminalId))) {
87 return false;
88 }
89 // Memorize the mapping to the old terminal id to the new terminal id.
90 terminalIdMap->insert(TerminalIdMap::value_type(i, nextNewTerminalId));
91 nextNewTerminalId++;
92 }
93 }
94 mSize = nextNewTerminalId;
95 return true;
96 }
97
98 } // namespace latinime
99