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