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