Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2017 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 ANDROID_UTIL_ENCODED_BUFFER_H
     18 #define ANDROID_UTIL_ENCODED_BUFFER_H
     19 
     20 #include <stdint.h>
     21 #include <vector>
     22 
     23 namespace android {
     24 namespace util {
     25 
     26 /**
     27  * A stream of bytes containing a read pointer and a write pointer,
     28  * backed by a set of fixed-size buffers.  There are write functions for the
     29  * primitive types stored by protocol buffers, but none of the logic
     30  * for tags, inner objects, or any of that.
     31  *
     32  * Terminology:
     33  *      *Pos:       Position in the whole data set (as if it were a single buffer).
     34  *      *Index:     Index of a buffer within the mBuffers list.
     35  *      *Offset:    Position within a buffer.
     36  */
     37 class EncodedBuffer
     38 {
     39 public:
     40     EncodedBuffer();
     41     EncodedBuffer(size_t chunkSize);
     42     ~EncodedBuffer();
     43 
     44     class Pointer {
     45     public:
     46         Pointer();
     47         Pointer(size_t chunkSize);
     48 
     49         size_t pos() const;
     50         size_t index() const;
     51         size_t offset() const;
     52 
     53         Pointer* move(size_t amt);
     54         inline Pointer* move() { return move(1); };
     55         Pointer* rewind();
     56 
     57         Pointer copy() const;
     58 
     59     private:
     60         size_t mChunkSize;
     61         size_t mIndex;
     62         size_t mOffset;
     63     };
     64 
     65     /**
     66      * Clears the buffer by rewinding its write pointer to avoid de/allocate buffers in heap.
     67      */
     68     void clear();
     69 
     70     /******************************** Write APIs ************************************************/
     71 
     72     /**
     73      * Returns the number of bytes written in the buffer
     74      */
     75     size_t size() const;
     76 
     77     /**
     78      * Returns the write pointer.
     79      */
     80     Pointer* wp();
     81 
     82     /**
     83      * Returns the current position of write pointer, if the write buffer is full, it will automatically
     84      * rotate to a new buffer with given chunkSize. If NULL is returned, it means NO_MEMORY
     85      */
     86     uint8_t* writeBuffer();
     87 
     88     /**
     89      * Returns the writeable size in the current write buffer .
     90      */
     91     size_t currentToWrite();
     92 
     93     /**
     94      * Write a single byte to the buffer.
     95      */
     96     void writeRawByte(uint8_t val);
     97 
     98     /**
     99      * Write a varint32 into the buffer. Return the size of the varint.
    100      */
    101     size_t writeRawVarint32(uint32_t val);
    102 
    103     /**
    104      * Write a varint64 into the buffer. Return the size of the varint.
    105      */
    106     size_t writeRawVarint64(uint64_t val);
    107 
    108     /**
    109      * Write Fixed32 into the buffer.
    110      */
    111     void writeRawFixed32(uint32_t val);
    112 
    113     /**
    114      * Write Fixed64 into the buffer.
    115      */
    116     void writeRawFixed64(uint64_t val);
    117 
    118     /**
    119      * Write a protobuf header. Return the size of the header.
    120      */
    121     size_t writeHeader(uint32_t fieldId, uint8_t wireType);
    122 
    123     /********************************* Edit APIs ************************************************/
    124     /**
    125      * Returns the edit pointer.
    126      */
    127     Pointer* ep();
    128 
    129     /**
    130      * Read a single byte at ep, and move ep to next byte;
    131      */
    132     uint8_t readRawByte();
    133 
    134     /**
    135      * Read varint starting at ep, ep will move to pos of next byte.
    136      */
    137     uint64_t readRawVarint();
    138 
    139     /**
    140      * Read 4 bytes starting at ep, ep will move to pos of next byte.
    141      */
    142     uint32_t readRawFixed32();
    143 
    144     /**
    145      * Read 8 bytes starting at ep, ep will move to pos of next byte.
    146      */
    147     uint64_t readRawFixed64();
    148 
    149     /**
    150      * Edit 4 bytes starting at pos.
    151      */
    152     void editRawFixed32(size_t pos, uint32_t val);
    153 
    154     /**
    155      * Copy _size_ bytes of data starting at __srcPos__ to wp, srcPos must be larger than wp.pos().
    156      */
    157     void copy(size_t srcPos, size_t size);
    158 
    159     /********************************* Read APIs ************************************************/
    160     class iterator;
    161     friend class iterator;
    162     class iterator {
    163     public:
    164         iterator(const EncodedBuffer& buffer);
    165 
    166         /**
    167          * Returns the number of bytes written in the buffer
    168          */
    169         size_t size() const;
    170 
    171         /**
    172          * Returns the size of total bytes read.
    173          */
    174         size_t bytesRead() const;
    175 
    176         /**
    177          * Returns the read pointer.
    178          */
    179         Pointer* rp();
    180 
    181         /**
    182          * Returns the current position of read pointer, if NULL is returned, it reaches end of buffer.
    183          */
    184         uint8_t const* readBuffer();
    185 
    186         /**
    187          * Returns the readable size in the current read buffer.
    188          */
    189         size_t currentToRead();
    190 
    191         /**
    192          * Returns true if next bytes is available for read.
    193          */
    194         bool hasNext();
    195 
    196         /**
    197          * Reads the current byte and moves pointer 1 bit.
    198          */
    199         uint8_t next();
    200 
    201         /**
    202          * Read varint from iterator, the iterator will point to next available byte.
    203          */
    204         uint64_t readRawVarint();
    205 
    206     private:
    207         const EncodedBuffer& mData;
    208         Pointer mRp;
    209     };
    210 
    211     /**
    212      * Returns the iterator of EncodedBuffer so it guarantees consumers won't be able to modified the buffer.
    213      */
    214     iterator begin() const;
    215 
    216 private:
    217     size_t mChunkSize;
    218     std::vector<uint8_t*> mBuffers;
    219 
    220     Pointer mWp;
    221     Pointer mEp;
    222 
    223     inline uint8_t* at(const Pointer& p) const; // helper function to get value
    224 };
    225 
    226 } // util
    227 } // android
    228 
    229 #endif // ANDROID_UTIL_ENCODED_BUFFER_H
    230 
    231