buffer_with_extendable_buffer.h revision c0c674cdc0721a374e140ad5ee1409c0498b3262
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_BUFFER_WITH_EXTENDABLE_BUFFER_H
18#define LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H
19
20#include <cstddef>
21#include <cstdint>
22#include <vector>
23
24#include "defines.h"
25#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
26#include "utils/byte_array_view.h"
27
28namespace latinime {
29
30// This is used as a buffer that can be extended for updatable dictionaries.
31// To optimize performance, raw pointer is directly used for reading buffer. The position has to be
32// adjusted to access additional buffer. On the other hand, this class does not provide writable
33// raw pointer but provides several methods that handle boundary checking for writing data.
34class BufferWithExtendableBuffer {
35 public:
36    static const size_t DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE;
37
38    BufferWithExtendableBuffer(const ReadWriteByteArrayView originalBuffer,
39            const int maxAdditionalBufferSize)
40            : mOriginalBuffer(originalBuffer), mAdditionalBuffer(), mUsedAdditionalBufferSize(0),
41              mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
42
43    // Without original buffer.
44    BufferWithExtendableBuffer(const int maxAdditionalBufferSize)
45            : mOriginalBuffer(), mAdditionalBuffer(), mUsedAdditionalBufferSize(0),
46              mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
47
48    AK_FORCE_INLINE int getTailPosition() const {
49        return mOriginalBuffer.size() + mUsedAdditionalBufferSize;
50    }
51
52    AK_FORCE_INLINE int getUsedAdditionalBufferSize() const {
53        return mUsedAdditionalBufferSize;
54    }
55
56    /**
57     * For reading.
58     */
59    AK_FORCE_INLINE bool isInAdditionalBuffer(const int position) const {
60        return position >= static_cast<int>(mOriginalBuffer.size());
61    }
62
63    // TODO: Resolve the issue that the address can be changed when the vector is resized.
64    // CAVEAT!: Be careful about array out of bound access with buffers
65    AK_FORCE_INLINE const uint8_t *getBuffer(const bool usesAdditionalBuffer) const {
66        if (usesAdditionalBuffer) {
67            return mAdditionalBuffer.data();
68        } else {
69            return mOriginalBuffer.data();
70        }
71    }
72
73    uint32_t readUint(const int size, const int pos) const;
74
75    uint32_t readUintAndAdvancePosition(const int size, int *const pos) const;
76
77    void readCodePointsAndAdvancePosition(const int maxCodePointCount,
78            int *const outCodePoints, int *outCodePointCount, int *const pos) const;
79
80    AK_FORCE_INLINE int getOriginalBufferSize() const {
81        return mOriginalBuffer.size();
82    }
83
84    AK_FORCE_INLINE bool isNearSizeLimit() const {
85        return mAdditionalBuffer.size() >= ((mMaxAdditionalBufferSize
86                * NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE) / 100);
87    }
88
89    bool extend(const int size);
90
91    /**
92     * For writing.
93     *
94     * Writing is allowed for original buffer, already written region of additional buffer and the
95     * tail of additional buffer.
96     */
97    bool writeUint(const uint32_t data, const int size, const int pos);
98
99    bool writeUintAndAdvancePosition(const uint32_t data, const int size, int *const pos);
100
101    bool writeCodePointsAndAdvancePosition(const int *const codePoints, const int codePointCount,
102            const bool writesTerminator, int *const pos);
103
104    bool copy(const BufferWithExtendableBuffer *const sourceBuffer);
105
106 private:
107    DISALLOW_COPY_AND_ASSIGN(BufferWithExtendableBuffer);
108
109    static const int NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE;
110    static const size_t EXTEND_ADDITIONAL_BUFFER_SIZE_STEP;
111
112    const ReadWriteByteArrayView mOriginalBuffer;
113    std::vector<uint8_t> mAdditionalBuffer;
114    int mUsedAdditionalBufferSize;
115    const size_t mMaxAdditionalBufferSize;
116
117    // Return if the buffer is successfully extended or not.
118    bool extendBuffer(const size_t size);
119
120    // Returns if it is possible to write size-bytes from pos. When pos is at the tail position of
121    // the additional buffer, try extending the buffer.
122    bool checkAndPrepareWriting(const int pos, const int size);
123};
124}
125#endif /* LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H */
126