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 <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