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