Home | History | Annotate | Download | only in src
      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 #define LOG_TAG "libprotoutil"
     17 
     18 #include <stdlib.h>
     19 
     20 #include <android/util/EncodedBuffer.h>
     21 #include <android/util/protobuf.h>
     22 #include <cutils/log.h>
     23 
     24 namespace android {
     25 namespace util {
     26 
     27 const size_t BUFFER_SIZE = 8 * 1024; // 8 KB
     28 
     29 EncodedBuffer::Pointer::Pointer() : Pointer(BUFFER_SIZE)
     30 {
     31 }
     32 
     33 EncodedBuffer::Pointer::Pointer(size_t chunkSize)
     34         :mIndex(0),
     35          mOffset(0)
     36 {
     37     mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
     38 }
     39 
     40 size_t
     41 EncodedBuffer::Pointer::pos() const
     42 {
     43     return mIndex * mChunkSize + mOffset;
     44 }
     45 
     46 size_t
     47 EncodedBuffer::Pointer::index() const
     48 {
     49     return mIndex;
     50 }
     51 
     52 size_t
     53 EncodedBuffer::Pointer::offset() const
     54 {
     55     return mOffset;
     56 }
     57 
     58 EncodedBuffer::Pointer*
     59 EncodedBuffer::Pointer::move(size_t amt)
     60 {
     61     size_t newOffset = mOffset + amt;
     62     mIndex += newOffset / mChunkSize;
     63     mOffset = newOffset % mChunkSize;
     64     return this;
     65 }
     66 
     67 EncodedBuffer::Pointer*
     68 EncodedBuffer::Pointer::rewind()
     69 {
     70     mIndex = 0;
     71     mOffset = 0;
     72     return this;
     73 }
     74 
     75 EncodedBuffer::Pointer
     76 EncodedBuffer::Pointer::copy() const
     77 {
     78     Pointer p = Pointer(mChunkSize);
     79     p.mIndex = mIndex;
     80     p.mOffset = mOffset;
     81     return p;
     82 }
     83 
     84 // ===========================================================
     85 EncodedBuffer::EncodedBuffer() : EncodedBuffer(0)
     86 {
     87 }
     88 
     89 EncodedBuffer::EncodedBuffer(size_t chunkSize)
     90         :mBuffers()
     91 {
     92     mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
     93     mWp = Pointer(mChunkSize);
     94     mEp = Pointer(mChunkSize);
     95 }
     96 
     97 EncodedBuffer::~EncodedBuffer()
     98 {
     99     for (size_t i=0; i<mBuffers.size(); i++) {
    100         uint8_t* buf = mBuffers[i];
    101         free(buf);
    102     }
    103 }
    104 
    105 inline uint8_t*
    106 EncodedBuffer::at(const Pointer& p) const
    107 {
    108     return mBuffers[p.index()] + p.offset();
    109 }
    110 
    111 void
    112 EncodedBuffer::clear()
    113 {
    114     mWp.rewind();
    115     mEp.rewind();
    116 }
    117 
    118 /******************************** Write APIs ************************************************/
    119 size_t
    120 EncodedBuffer::size() const
    121 {
    122     return mWp.pos();
    123 }
    124 
    125 EncodedBuffer::Pointer*
    126 EncodedBuffer::wp()
    127 {
    128     return &mWp;
    129 }
    130 
    131 uint8_t*
    132 EncodedBuffer::writeBuffer()
    133 {
    134     // This prevents write pointer move too fast than allocating the buffer.
    135     if (mWp.index() > mBuffers.size()) return NULL;
    136     uint8_t* buf = NULL;
    137     if (mWp.index() == mBuffers.size()) {
    138         buf = (uint8_t*)malloc(mChunkSize);
    139 
    140         if (buf == NULL) return NULL; // This indicates NO_MEMORY
    141 
    142         mBuffers.push_back(buf);
    143     }
    144     return at(mWp);
    145 }
    146 
    147 size_t
    148 EncodedBuffer::currentToWrite()
    149 {
    150     return mChunkSize - mWp.offset();
    151 }
    152 
    153 void
    154 EncodedBuffer::writeRawByte(uint8_t val)
    155 {
    156     *writeBuffer() = val;
    157     mWp.move();
    158 }
    159 
    160 size_t
    161 EncodedBuffer::writeRawVarint64(uint64_t val)
    162 {
    163     size_t size = 0;
    164     while (true) {
    165         size++;
    166         if ((val & ~0x7F) == 0) {
    167             writeRawByte((uint8_t) val);
    168             return size;
    169         } else {
    170             writeRawByte((uint8_t)((val & 0x7F) | 0x80));
    171             val >>= 7;
    172         }
    173     }
    174 }
    175 
    176 size_t
    177 EncodedBuffer::writeRawVarint32(uint32_t val)
    178 {
    179     uint64_t v =(uint64_t)val;
    180     return writeRawVarint64(v);
    181 }
    182 
    183 void
    184 EncodedBuffer::writeRawFixed32(uint32_t val)
    185 {
    186     writeRawByte((uint8_t) val);
    187     writeRawByte((uint8_t) (val>>8));
    188     writeRawByte((uint8_t) (val>>16));
    189     writeRawByte((uint8_t) (val>>24));
    190 }
    191 
    192 void
    193 EncodedBuffer::writeRawFixed64(uint64_t val)
    194 {
    195     writeRawByte((uint8_t) val);
    196     writeRawByte((uint8_t) (val>>8));
    197     writeRawByte((uint8_t) (val>>16));
    198     writeRawByte((uint8_t) (val>>24));
    199     writeRawByte((uint8_t) (val>>32));
    200     writeRawByte((uint8_t) (val>>40));
    201     writeRawByte((uint8_t) (val>>48));
    202     writeRawByte((uint8_t) (val>>56));
    203 }
    204 
    205 size_t
    206 EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
    207 {
    208     return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
    209 }
    210 
    211 /******************************** Edit APIs ************************************************/
    212 EncodedBuffer::Pointer*
    213 EncodedBuffer::ep()
    214 {
    215     return &mEp;
    216 }
    217 
    218 uint8_t
    219 EncodedBuffer::readRawByte()
    220 {
    221     uint8_t val = *at(mEp);
    222     mEp.move();
    223     return val;
    224 }
    225 
    226 uint64_t
    227 EncodedBuffer::readRawVarint()
    228 {
    229     uint64_t val = 0, shift = 0;
    230     size_t start = mEp.pos();
    231     while (true) {
    232         uint8_t byte = readRawByte();
    233         val |= (UINT64_C(0x7F) & byte) << shift;
    234         if ((byte & 0x80) == 0) break;
    235         shift += 7;
    236     }
    237     return val;
    238 }
    239 
    240 uint32_t
    241 EncodedBuffer::readRawFixed32()
    242 {
    243     uint32_t val = 0;
    244     for (auto i=0; i<32; i+=8) {
    245         val += (uint32_t)readRawByte() << i;
    246     }
    247     return val;
    248 }
    249 
    250 uint64_t
    251 EncodedBuffer::readRawFixed64()
    252 {
    253     uint64_t val = 0;
    254     for (auto i=0; i<64; i+=8) {
    255         val += (uint64_t)readRawByte() << i;
    256     }
    257     return val;
    258 }
    259 
    260 void
    261 EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
    262 {
    263     size_t oldPos = mEp.pos();
    264     mEp.rewind()->move(pos);
    265     for (auto i=0; i<32; i+=8) {
    266         *at(mEp) = (uint8_t) (val >> i);
    267         mEp.move();
    268     }
    269     mEp.rewind()->move(oldPos);
    270 }
    271 
    272 void
    273 EncodedBuffer::copy(size_t srcPos, size_t size)
    274 {
    275     if (size == 0) return;
    276     Pointer cp(mChunkSize);
    277     cp.move(srcPos);
    278 
    279     while (cp.pos() < srcPos + size) {
    280         writeRawByte(*at(cp));
    281         cp.move();
    282     }
    283 }
    284 
    285 /********************************* Read APIs ************************************************/
    286 EncodedBuffer::iterator
    287 EncodedBuffer::begin() const
    288 {
    289     return EncodedBuffer::iterator(*this);
    290 }
    291 
    292 EncodedBuffer::iterator::iterator(const EncodedBuffer& buffer)
    293         :mData(buffer),
    294          mRp(buffer.mChunkSize)
    295 {
    296 }
    297 
    298 size_t
    299 EncodedBuffer::iterator::size() const
    300 {
    301     return mData.size();
    302 }
    303 
    304 size_t
    305 EncodedBuffer::iterator::bytesRead() const
    306 {
    307     return mRp.pos();
    308 }
    309 
    310 EncodedBuffer::Pointer*
    311 EncodedBuffer::iterator::rp()
    312 {
    313     return &mRp;
    314 }
    315 
    316 uint8_t const*
    317 EncodedBuffer::iterator::readBuffer()
    318 {
    319     return hasNext() ? const_cast<uint8_t const*>(mData.at(mRp)) : NULL;
    320 }
    321 
    322 size_t
    323 EncodedBuffer::iterator::currentToRead()
    324 {
    325     return (mData.mWp.index() > mRp.index()) ?
    326             mData.mChunkSize - mRp.offset() :
    327             mData.mWp.offset() - mRp.offset();
    328 }
    329 
    330 bool
    331 EncodedBuffer::iterator::hasNext()
    332 {
    333     return mRp.pos() < mData.mWp.pos();
    334 }
    335 
    336 uint8_t
    337 EncodedBuffer::iterator::next()
    338 {
    339     uint8_t res = *(mData.at(mRp));
    340     mRp.move();
    341     return res;
    342 }
    343 
    344 uint64_t
    345 EncodedBuffer::iterator::readRawVarint()
    346 {
    347     uint64_t val = 0, shift = 0;
    348     while (true) {
    349         uint8_t byte = next();
    350         val |= (INT64_C(0x7F) & byte) << shift;
    351         if ((byte & 0x80) == 0) break;
    352         shift += 7;
    353     }
    354     return val;
    355 }
    356 
    357 } // util
    358 } // android
    359