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 status_t
    212 EncodedBuffer::writeRaw(uint8_t const* buf, size_t size)
    213 {
    214     while (size > 0) {
    215         uint8_t* target = writeBuffer();
    216         if (target == NULL) {
    217             return -ENOMEM;
    218         }
    219         size_t chunk = currentToWrite();
    220         if (chunk > size) {
    221             chunk = size;
    222         }
    223         memcpy(target, buf, chunk);
    224         size -= chunk;
    225         buf += chunk;
    226         mWp.move(chunk);
    227     }
    228     return NO_ERROR;
    229 }
    230 
    231 status_t
    232 EncodedBuffer::writeRaw(const sp<ProtoReader>& reader)
    233 {
    234     status_t err;
    235     uint8_t const* buf;
    236     while ((buf = reader->readBuffer()) != nullptr) {
    237         size_t amt = reader->currentToRead();
    238         err = writeRaw(buf, amt);
    239         reader->move(amt);
    240         if (err != NO_ERROR) {
    241             return err;
    242         }
    243     }
    244     return NO_ERROR;
    245 }
    246 
    247 status_t
    248 EncodedBuffer::writeRaw(const sp<ProtoReader>& reader, size_t size)
    249 {
    250     status_t err;
    251     uint8_t const* buf;
    252     while (size > 0 && (buf = reader->readBuffer()) != nullptr) {
    253         size_t amt = reader->currentToRead();
    254         if (size < amt) {
    255             amt = size;
    256         }
    257         err = writeRaw(buf, amt);
    258         reader->move(amt);
    259         size -= amt;
    260         if (err != NO_ERROR) {
    261             return err;
    262         }
    263     }
    264     return size == 0 ? NO_ERROR : NOT_ENOUGH_DATA;
    265 }
    266 
    267 
    268 /******************************** Edit APIs ************************************************/
    269 EncodedBuffer::Pointer*
    270 EncodedBuffer::ep()
    271 {
    272     return &mEp;
    273 }
    274 
    275 uint8_t
    276 EncodedBuffer::readRawByte()
    277 {
    278     uint8_t val = *at(mEp);
    279     mEp.move();
    280     return val;
    281 }
    282 
    283 uint64_t
    284 EncodedBuffer::readRawVarint()
    285 {
    286     uint64_t val = 0, shift = 0;
    287     size_t start = mEp.pos();
    288     while (true) {
    289         uint8_t byte = readRawByte();
    290         val |= (UINT64_C(0x7F) & byte) << shift;
    291         if ((byte & 0x80) == 0) break;
    292         shift += 7;
    293     }
    294     return val;
    295 }
    296 
    297 uint32_t
    298 EncodedBuffer::readRawFixed32()
    299 {
    300     uint32_t val = 0;
    301     for (auto i=0; i<32; i+=8) {
    302         val += (uint32_t)readRawByte() << i;
    303     }
    304     return val;
    305 }
    306 
    307 uint64_t
    308 EncodedBuffer::readRawFixed64()
    309 {
    310     uint64_t val = 0;
    311     for (auto i=0; i<64; i+=8) {
    312         val += (uint64_t)readRawByte() << i;
    313     }
    314     return val;
    315 }
    316 
    317 void
    318 EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
    319 {
    320     size_t oldPos = mEp.pos();
    321     mEp.rewind()->move(pos);
    322     for (auto i=0; i<32; i+=8) {
    323         *at(mEp) = (uint8_t) (val >> i);
    324         mEp.move();
    325     }
    326     mEp.rewind()->move(oldPos);
    327 }
    328 
    329 void
    330 EncodedBuffer::copy(size_t srcPos, size_t size)
    331 {
    332     if (size == 0) return;
    333     Pointer cp(mChunkSize);
    334     cp.move(srcPos);
    335 
    336     while (cp.pos() < srcPos + size) {
    337         writeRawByte(*at(cp));
    338         cp.move();
    339     }
    340 }
    341 
    342 /********************************* Read APIs ************************************************/
    343 sp<ProtoReader>
    344 EncodedBuffer::read()
    345 {
    346     return new EncodedBuffer::Reader(this);
    347 }
    348 
    349 EncodedBuffer::Reader::Reader(const sp<EncodedBuffer>& buffer)
    350         :mData(buffer),
    351          mRp(buffer->mChunkSize)
    352 {
    353 }
    354 
    355 EncodedBuffer::Reader::~Reader() {
    356 }
    357 
    358 ssize_t
    359 EncodedBuffer::Reader::size() const
    360 {
    361     return (ssize_t)mData->size();
    362 }
    363 
    364 size_t
    365 EncodedBuffer::Reader::bytesRead() const
    366 {
    367     return mRp.pos();
    368 }
    369 
    370 uint8_t const*
    371 EncodedBuffer::Reader::readBuffer()
    372 {
    373     return hasNext() ? const_cast<uint8_t const*>(mData->at(mRp)) : NULL;
    374 }
    375 
    376 size_t
    377 EncodedBuffer::Reader::currentToRead()
    378 {
    379     return (mData->mWp.index() > mRp.index()) ?
    380             mData->mChunkSize - mRp.offset() :
    381             mData->mWp.offset() - mRp.offset();
    382 }
    383 
    384 bool
    385 EncodedBuffer::Reader::hasNext()
    386 {
    387     return mRp.pos() < mData->mWp.pos();
    388 }
    389 
    390 uint8_t
    391 EncodedBuffer::Reader::next()
    392 {
    393     uint8_t res = *(mData->at(mRp));
    394     mRp.move();
    395     return res;
    396 }
    397 
    398 uint64_t
    399 EncodedBuffer::Reader::readRawVarint()
    400 {
    401     uint64_t val = 0, shift = 0;
    402     while (true) {
    403         uint8_t byte = next();
    404         val |= (INT64_C(0x7F) & byte) << shift;
    405         if ((byte & 0x80) == 0) break;
    406         shift += 7;
    407     }
    408     return val;
    409 }
    410 
    411 void
    412 EncodedBuffer::Reader::move(size_t amt)
    413 {
    414     mRp.move(amt);
    415 }
    416 
    417 } // util
    418 } // android
    419