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 "dictionary/utils/byte_array_utils.h" 26 #include "utils/byte_array_view.h" 27 28 namespace 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. 34 class BufferWithExtendableBuffer { 35 public: 36 static const size_t DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE; 37 BufferWithExtendableBuffer(const ReadWriteByteArrayView originalBuffer,const int maxAdditionalBufferSize)38 BufferWithExtendableBuffer(const ReadWriteByteArrayView originalBuffer, 39 const int maxAdditionalBufferSize) 40 : mOriginalBuffer(originalBuffer), mAdditionalBuffer(), mUsedAdditionalBufferSize(0), 41 mMaxAdditionalBufferSize(maxAdditionalBufferSize) {} 42 43 // Without original buffer. BufferWithExtendableBuffer(const int maxAdditionalBufferSize)44 BufferWithExtendableBuffer(const int maxAdditionalBufferSize) 45 : mOriginalBuffer(), mAdditionalBuffer(), mUsedAdditionalBufferSize(0), 46 mMaxAdditionalBufferSize(maxAdditionalBufferSize) {} 47 getTailPosition()48 AK_FORCE_INLINE int getTailPosition() const { 49 return mOriginalBuffer.size() + mUsedAdditionalBufferSize; 50 } 51 getUsedAdditionalBufferSize()52 AK_FORCE_INLINE int getUsedAdditionalBufferSize() const { 53 return mUsedAdditionalBufferSize; 54 } 55 56 /** 57 * For reading. 58 */ isInAdditionalBuffer(const int position)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 getBuffer(const bool usesAdditionalBuffer)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 getOriginalBufferSize()80 AK_FORCE_INLINE int getOriginalBufferSize() const { 81 return mOriginalBuffer.size(); 82 } 83 isNearSizeLimit()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