1/*
2 * Copyright (C) 2014, 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/ver4_pt_node_array_reader.h"
18
19#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
20#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
21#include "dictionary/utils/buffer_with_extendable_buffer.h"
22
23namespace latinime {
24
25bool Ver4PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
26        int *const outPtNodeCount, int *const outFirstPtNodePos) const {
27    if (ptNodeArrayPos < 0 || ptNodeArrayPos >= mBuffer->getTailPosition()) {
28        // Reading invalid position because of a bug or a broken dictionary.
29        AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %d",
30                ptNodeArrayPos, mBuffer->getTailPosition());
31        ASSERT(false);
32        return false;
33    }
34    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodeArrayPos);
35    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
36    int readingPos = ptNodeArrayPos;
37    if (usesAdditionalBuffer) {
38        readingPos -= mBuffer->getOriginalBufferSize();
39    }
40    const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
41            dictBuf, &readingPos);
42    if (usesAdditionalBuffer) {
43        readingPos += mBuffer->getOriginalBufferSize();
44    }
45    if (ptNodeCountInArray < 0) {
46        AKLOGE("Invalid PtNode count in an array: %d.", ptNodeCountInArray);
47        return false;
48    }
49    *outPtNodeCount = ptNodeCountInArray;
50    *outFirstPtNodePos = readingPos;
51    return true;
52}
53
54bool Ver4PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
55        int *const outNextPtNodeArrayPos) const {
56    if (forwordLinkPos < 0 || forwordLinkPos >= mBuffer->getTailPosition()) {
57        // Reading invalid position because of bug or broken dictionary.
58        AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %d",
59                forwordLinkPos, mBuffer->getTailPosition());
60        ASSERT(false);
61        return false;
62    }
63    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(forwordLinkPos);
64    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
65    int readingPos = forwordLinkPos;
66    if (usesAdditionalBuffer) {
67        readingPos -= mBuffer->getOriginalBufferSize();
68    }
69    const int nextPtNodeArrayOffset =
70            DynamicPtReadingUtils::getForwardLinkPosition(dictBuf, readingPos);
71    if (DynamicPtReadingUtils::isValidForwardLinkPosition(nextPtNodeArrayOffset)) {
72        *outNextPtNodeArrayPos = forwordLinkPos + nextPtNodeArrayOffset;
73    } else {
74        *outNextPtNodeArrayPos = NOT_A_DICT_POS;
75    }
76    return true;
77}
78
79} // namespace latinime
80