12f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi/*
22f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * Copyright (C) 2013 The Android Open Source Project
32f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi *
42f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * Licensed under the Apache License, Version 2.0 (the "License");
52f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * you may not use this file except in compliance with the License.
62f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * You may obtain a copy of the License at
72f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi *
82f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi *      http://www.apache.org/licenses/LICENSE-2.0
92f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi *
102f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * Unless required by applicable law or agreed to in writing, software
112f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * distributed under the License is distributed on an "AS IS" BASIS,
122f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * See the License for the specific language governing permissions and
142f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * limitations under the License.
152f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi */
162f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
172f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi#ifndef LATINIME_DYNAMIC_SHORTCUT_LIST_POLICY_H
182f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi#define LATINIME_DYNAMIC_SHORTCUT_LIST_POLICY_H
192f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
202f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi#include <stdint.h>
212f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
222f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi#include "defines.h"
232f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
242f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h"
252660f83a123b54af02a829cf941a0348194aa3c5Keisuke Kuroyanagi#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
262f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
272f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanaginamespace latinime {
282f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
292f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi/*
302f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi * This is a dynamic version of ShortcutListPolicy and supports an additional buffer.
312f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi */
322f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagiclass DynamicShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
332f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi public:
34b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi    explicit DynamicShortcutListPolicy(const BufferWithExtendableBuffer *const buffer)
353e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi            : mBuffer(buffer) {}
362f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
372f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    ~DynamicShortcutListPolicy() {}
382f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
392f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    int getStartPos(const int pos) const {
402f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        if (pos == NOT_A_DICT_POS) {
412f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi            return NOT_A_DICT_POS;
422f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        }
432f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        return pos + ShortcutListReadingUtils::getShortcutListSizeFieldSize();
442f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    }
452f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
462f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
472f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
482f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi            int *const pos) const {
493e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*pos);
503e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        const uint8_t *const buffer = mBuffer->getBuffer(usesAdditionalBuffer);
512f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        if (usesAdditionalBuffer) {
523e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi            *pos -= mBuffer->getOriginalBufferSize();
532f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        }
542f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        const ShortcutListReadingUtils::ShortcutFlags flags =
552f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi                ShortcutListReadingUtils::getFlagsAndForwardPointer(buffer, pos);
562f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        if (outHasNext) {
572f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi            *outHasNext = ShortcutListReadingUtils::hasNext(flags);
582f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        }
592f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        if (outIsWhitelist) {
602f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(flags);
612f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        }
622f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        if (outCodePoint) {
632f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi            *outCodePointCount = ShortcutListReadingUtils::readShortcutTarget(
642f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi                    buffer, maxCodePointCount, outCodePoint, pos);
652f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        }
662f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        if (usesAdditionalBuffer) {
673e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi            *pos += mBuffer->getOriginalBufferSize();
682f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        }
692f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    }
702f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
712f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    void skipAllShortcuts(int *const pos) const {
723e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*pos);
733e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        const uint8_t *const buffer = mBuffer->getBuffer(usesAdditionalBuffer);
743e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        if (usesAdditionalBuffer) {
753e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi            *pos -= mBuffer->getOriginalBufferSize();
763e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        }
773e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        const int shortcutListSize = ShortcutListReadingUtils
783e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi                ::getShortcutListSizeAndForwardPointer(buffer, pos);
793e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        *pos += shortcutListSize;
803e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi        if (usesAdditionalBuffer) {
813e76487c6c95ccec49622b9d7e0b45efff97f937Keisuke Kuroyanagi            *pos += mBuffer->getOriginalBufferSize();
822f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi        }
832f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    }
842f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
85b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi    // Copy shortcuts from the shortcut list that starts at fromPos in mBuffer to toPos in
86b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi    // bufferToWrite and advance these positions after the shortcut lists. This returns whether
87b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi    // the copy was succeeded or not.
88b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi    bool copyAllShortcutsAndReturnIfSucceededOrNot(BufferWithExtendableBuffer *const bufferToWrite,
89b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi            int *const fromPos, int *const toPos) const {
909e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(*fromPos);
919e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        if (usesAdditionalBuffer) {
929e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi            *fromPos -= mBuffer->getOriginalBufferSize();
939e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        }
949e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        const int shortcutListSize = ShortcutListReadingUtils
95b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi                ::getShortcutListSizeAndForwardPointer(mBuffer->getBuffer(usesAdditionalBuffer),
96b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi                        fromPos);
979e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        // Copy shortcut list size.
98b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi        if (!bufferToWrite->writeUintAndAdvancePosition(
999e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi                shortcutListSize + ShortcutListReadingUtils::getShortcutListSizeFieldSize(),
100c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi                ShortcutListReadingUtils::getShortcutListSizeFieldSize(), toPos)) {
101c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi            return false;
102c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi        }
103c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi        // Copy shortcut list.
1049e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        for (int i = 0; i < shortcutListSize; ++i) {
105c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi            const uint8_t data = ByteArrayUtils::readUint8AndAdvancePosition(
106c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi                    mBuffer->getBuffer(usesAdditionalBuffer), fromPos);
107b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi            if (!bufferToWrite->writeUintAndAdvancePosition(data, 1 /* size */, toPos)) {
108c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi                return false;
109c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi            }
1109e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        }
1119e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        if (usesAdditionalBuffer) {
1129e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi            *fromPos += mBuffer->getOriginalBufferSize();
1139e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi        }
114c987120cbcb94f8ab2d4994d548af0dbbb04a4d5Keisuke Kuroyanagi        return true;
1159e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi    }
1169e3082e0168ff40ec532d5fef162d93426b550a1Keisuke Kuroyanagi
1172f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi private:
1182f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicShortcutListPolicy);
1192f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi
120b7e8a9abf585181345b32631e4c02747ee60a1a0Keisuke Kuroyanagi    const BufferWithExtendableBuffer *const mBuffer;
1212f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi};
1222f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi} // namespace latinime
1232f0c1253e288d0670416bf8fc45b77962e68e250Keisuke Kuroyanagi#endif // LATINIME_DYNAMIC_SHORTCUT_LIST_POLICY_H
124