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 24namespace android { 25namespace util { 26 27const size_t BUFFER_SIZE = 8 * 1024; // 8 KB 28 29EncodedBuffer::Pointer::Pointer() : Pointer(BUFFER_SIZE) 30{ 31} 32 33EncodedBuffer::Pointer::Pointer(size_t chunkSize) 34 :mIndex(0), 35 mOffset(0) 36{ 37 mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize; 38} 39 40size_t 41EncodedBuffer::Pointer::pos() const 42{ 43 return mIndex * mChunkSize + mOffset; 44} 45 46size_t 47EncodedBuffer::Pointer::index() const 48{ 49 return mIndex; 50} 51 52size_t 53EncodedBuffer::Pointer::offset() const 54{ 55 return mOffset; 56} 57 58EncodedBuffer::Pointer* 59EncodedBuffer::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 67EncodedBuffer::Pointer* 68EncodedBuffer::Pointer::rewind() 69{ 70 mIndex = 0; 71 mOffset = 0; 72 return this; 73} 74 75EncodedBuffer::Pointer 76EncodedBuffer::Pointer::copy() const 77{ 78 Pointer p = Pointer(mChunkSize); 79 p.mIndex = mIndex; 80 p.mOffset = mOffset; 81 return p; 82} 83 84// =========================================================== 85EncodedBuffer::EncodedBuffer() : EncodedBuffer(0) 86{ 87} 88 89EncodedBuffer::EncodedBuffer(size_t chunkSize) 90 :mBuffers() 91{ 92 mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize; 93 mWp = Pointer(mChunkSize); 94 mEp = Pointer(mChunkSize); 95} 96 97EncodedBuffer::~EncodedBuffer() 98{ 99 for (size_t i=0; i<mBuffers.size(); i++) { 100 uint8_t* buf = mBuffers[i]; 101 free(buf); 102 } 103} 104 105inline uint8_t* 106EncodedBuffer::at(const Pointer& p) const 107{ 108 return mBuffers[p.index()] + p.offset(); 109} 110 111void 112EncodedBuffer::clear() 113{ 114 mWp.rewind(); 115 mEp.rewind(); 116} 117 118/******************************** Write APIs ************************************************/ 119size_t 120EncodedBuffer::size() const 121{ 122 return mWp.pos(); 123} 124 125EncodedBuffer::Pointer* 126EncodedBuffer::wp() 127{ 128 return &mWp; 129} 130 131uint8_t* 132EncodedBuffer::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 147size_t 148EncodedBuffer::currentToWrite() 149{ 150 return mChunkSize - mWp.offset(); 151} 152 153void 154EncodedBuffer::writeRawByte(uint8_t val) 155{ 156 *writeBuffer() = val; 157 mWp.move(); 158} 159 160size_t 161EncodedBuffer::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 176size_t 177EncodedBuffer::writeRawVarint32(uint32_t val) 178{ 179 uint64_t v =(uint64_t)val; 180 return writeRawVarint64(v); 181} 182 183void 184EncodedBuffer::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 192void 193EncodedBuffer::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 205size_t 206EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType) 207{ 208 return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType); 209} 210 211/******************************** Edit APIs ************************************************/ 212EncodedBuffer::Pointer* 213EncodedBuffer::ep() 214{ 215 return &mEp; 216} 217 218uint8_t 219EncodedBuffer::readRawByte() 220{ 221 uint8_t val = *at(mEp); 222 mEp.move(); 223 return val; 224} 225 226uint64_t 227EncodedBuffer::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 240uint32_t 241EncodedBuffer::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 250uint64_t 251EncodedBuffer::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 260void 261EncodedBuffer::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 272void 273EncodedBuffer::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 ************************************************/ 286EncodedBuffer::iterator 287EncodedBuffer::begin() const 288{ 289 return EncodedBuffer::iterator(*this); 290} 291 292EncodedBuffer::iterator::iterator(const EncodedBuffer& buffer) 293 :mData(buffer), 294 mRp(buffer.mChunkSize) 295{ 296} 297 298size_t 299EncodedBuffer::iterator::size() const 300{ 301 return mData.size(); 302} 303 304size_t 305EncodedBuffer::iterator::bytesRead() const 306{ 307 return mRp.pos(); 308} 309 310EncodedBuffer::Pointer* 311EncodedBuffer::iterator::rp() 312{ 313 return &mRp; 314} 315 316uint8_t const* 317EncodedBuffer::iterator::readBuffer() 318{ 319 return hasNext() ? const_cast<uint8_t const*>(mData.at(mRp)) : NULL; 320} 321 322size_t 323EncodedBuffer::iterator::currentToRead() 324{ 325 return (mData.mWp.index() > mRp.index()) ? 326 mData.mChunkSize - mRp.offset() : 327 mData.mWp.offset() - mRp.offset(); 328} 329 330bool 331EncodedBuffer::iterator::hasNext() 332{ 333 return mRp.pos() < mData.mWp.pos(); 334} 335 336uint8_t 337EncodedBuffer::iterator::next() 338{ 339 uint8_t res = *(mData.at(mRp)); 340 mRp.move(); 341 return res; 342} 343 344uint64_t 345EncodedBuffer::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