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