Home | History | Annotate | Download | only in utils
      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 
     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