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#ifndef LATINIME_DYNAMIC_SHORTCUT_LIST_POLICY_H
18#define LATINIME_DYNAMIC_SHORTCUT_LIST_POLICY_H
19
20#include <stdint.h>
21
22#include "defines.h"
23#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
24#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h"
25#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
26
27namespace latinime {
28
29/*
30 * This is a dynamic version of ShortcutListPolicy and supports an additional buffer.
31 */
32class DynamicShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
33 public:
34    explicit DynamicShortcutListPolicy(const BufferWithExtendableBuffer *const buffer)
35            : mBuffer(buffer) {}
36
37    ~DynamicShortcutListPolicy() {}
38
39    int getStartPos(const int pos) const {
40        if (pos == NOT_A_DICT_POS) {
41            return NOT_A_DICT_POS;
42        }
43        return pos + ShortcutListReadingUtils::getShortcutListSizeFieldSize();
44    }
45
46    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
47            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
48            int *const pos) const {
49        const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*pos);
50        const uint8_t *const buffer = mBuffer->getBuffer(usesAdditionalBuffer);
51        if (usesAdditionalBuffer) {
52            *pos -= mBuffer->getOriginalBufferSize();
53        }
54        const ShortcutListReadingUtils::ShortcutFlags flags =
55                ShortcutListReadingUtils::getFlagsAndForwardPointer(buffer, pos);
56        if (outHasNext) {
57            *outHasNext = ShortcutListReadingUtils::hasNext(flags);
58        }
59        if (outIsWhitelist) {
60            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(flags);
61        }
62        if (outCodePoint) {
63            *outCodePointCount = ShortcutListReadingUtils::readShortcutTarget(
64                    buffer, maxCodePointCount, outCodePoint, pos);
65        }
66        if (usesAdditionalBuffer) {
67            *pos += mBuffer->getOriginalBufferSize();
68        }
69    }
70
71    void skipAllShortcuts(int *const pos) const {
72        const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*pos);
73        const uint8_t *const buffer = mBuffer->getBuffer(usesAdditionalBuffer);
74        if (usesAdditionalBuffer) {
75            *pos -= mBuffer->getOriginalBufferSize();
76        }
77        const int shortcutListSize = ShortcutListReadingUtils
78                ::getShortcutListSizeAndForwardPointer(buffer, pos);
79        *pos += shortcutListSize;
80        if (usesAdditionalBuffer) {
81            *pos += mBuffer->getOriginalBufferSize();
82        }
83    }
84
85    // Copy shortcuts from the shortcut list that starts at fromPos in mBuffer to toPos in
86    // bufferToWrite and advance these positions after the shortcut lists. This returns whether
87    // the copy was succeeded or not.
88    bool copyAllShortcutsAndReturnIfSucceededOrNot(BufferWithExtendableBuffer *const bufferToWrite,
89            int *const fromPos, int *const toPos) const {
90        const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*fromPos);
91        if (usesAdditionalBuffer) {
92            *fromPos -= mBuffer->getOriginalBufferSize();
93        }
94        const int shortcutListSize = ShortcutListReadingUtils
95                ::getShortcutListSizeAndForwardPointer(mBuffer->getBuffer(usesAdditionalBuffer),
96                        fromPos);
97        // Copy shortcut list size.
98        if (!bufferToWrite->writeUintAndAdvancePosition(
99                shortcutListSize + ShortcutListReadingUtils::getShortcutListSizeFieldSize(),
100                ShortcutListReadingUtils::getShortcutListSizeFieldSize(), toPos)) {
101            return false;
102        }
103        // Copy shortcut list.
104        for (int i = 0; i < shortcutListSize; ++i) {
105            const uint8_t data = ByteArrayUtils::readUint8AndAdvancePosition(
106                    mBuffer->getBuffer(usesAdditionalBuffer), fromPos);
107            if (!bufferToWrite->writeUintAndAdvancePosition(data, 1 /* size */, toPos)) {
108                return false;
109            }
110        }
111        if (usesAdditionalBuffer) {
112            *fromPos += mBuffer->getOriginalBufferSize();
113        }
114        return true;
115    }
116
117 private:
118    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicShortcutListPolicy);
119
120    const BufferWithExtendableBuffer *const mBuffer;
121};
122} // namespace latinime
123#endif // LATINIME_DYNAMIC_SHORTCUT_LIST_POLICY_H
124