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 
Pointer()29 EncodedBuffer::Pointer::Pointer() : Pointer(BUFFER_SIZE)
30 {
31 }
32 
Pointer(size_t chunkSize)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
pos() const41 EncodedBuffer::Pointer::pos() const
42 {
43     return mIndex * mChunkSize + mOffset;
44 }
45 
46 size_t
index() const47 EncodedBuffer::Pointer::index() const
48 {
49     return mIndex;
50 }
51 
52 size_t
offset() const53 EncodedBuffer::Pointer::offset() const
54 {
55     return mOffset;
56 }
57 
58 EncodedBuffer::Pointer*
move(size_t amt)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*
rewind()68 EncodedBuffer::Pointer::rewind()
69 {
70     mIndex = 0;
71     mOffset = 0;
72     return this;
73 }
74 
75 EncodedBuffer::Pointer
copy() const76 EncodedBuffer::Pointer::copy() const
77 {
78     Pointer p = Pointer(mChunkSize);
79     p.mIndex = mIndex;
80     p.mOffset = mOffset;
81     return p;
82 }
83 
84 // ===========================================================
EncodedBuffer()85 EncodedBuffer::EncodedBuffer() : EncodedBuffer(0)
86 {
87 }
88 
EncodedBuffer(size_t chunkSize)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 
~EncodedBuffer()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*
at(const Pointer & p) const106 EncodedBuffer::at(const Pointer& p) const
107 {
108     return mBuffers[p.index()] + p.offset();
109 }
110 
111 void
clear()112 EncodedBuffer::clear()
113 {
114     mWp.rewind();
115     mEp.rewind();
116 }
117 
118 /******************************** Write APIs ************************************************/
119 size_t
size() const120 EncodedBuffer::size() const
121 {
122     return mWp.pos();
123 }
124 
125 EncodedBuffer::Pointer*
wp()126 EncodedBuffer::wp()
127 {
128     return &mWp;
129 }
130 
131 uint8_t*
writeBuffer()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
currentToWrite()148 EncodedBuffer::currentToWrite()
149 {
150     return mChunkSize - mWp.offset();
151 }
152 
153 void
writeRawByte(uint8_t val)154 EncodedBuffer::writeRawByte(uint8_t val)
155 {
156     *writeBuffer() = val;
157     mWp.move();
158 }
159 
160 size_t
writeRawVarint64(uint64_t val)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
writeRawVarint32(uint32_t val)177 EncodedBuffer::writeRawVarint32(uint32_t val)
178 {
179     uint64_t v =(uint64_t)val;
180     return writeRawVarint64(v);
181 }
182 
183 void
writeRawFixed32(uint32_t val)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
writeRawFixed64(uint64_t val)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
writeHeader(uint32_t fieldId,uint8_t wireType)206 EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
207 {
208     return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
209 }
210 
211 status_t
writeRaw(uint8_t const * buf,size_t size)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
writeRaw(const sp<ProtoReader> & reader)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
writeRaw(const sp<ProtoReader> & reader,size_t size)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*
ep()270 EncodedBuffer::ep()
271 {
272     return &mEp;
273 }
274 
275 uint8_t
readRawByte()276 EncodedBuffer::readRawByte()
277 {
278     uint8_t val = *at(mEp);
279     mEp.move();
280     return val;
281 }
282 
283 uint64_t
readRawVarint()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
readRawFixed32()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
readRawFixed64()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
editRawFixed32(size_t pos,uint32_t val)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
copy(size_t srcPos,size_t size)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>
read()344 EncodedBuffer::read()
345 {
346     return new EncodedBuffer::Reader(this);
347 }
348 
Reader(const sp<EncodedBuffer> & buffer)349 EncodedBuffer::Reader::Reader(const sp<EncodedBuffer>& buffer)
350         :mData(buffer),
351          mRp(buffer->mChunkSize)
352 {
353 }
354 
~Reader()355 EncodedBuffer::Reader::~Reader() {
356 }
357 
358 ssize_t
size() const359 EncodedBuffer::Reader::size() const
360 {
361     return (ssize_t)mData->size();
362 }
363 
364 size_t
bytesRead() const365 EncodedBuffer::Reader::bytesRead() const
366 {
367     return mRp.pos();
368 }
369 
370 uint8_t const*
readBuffer()371 EncodedBuffer::Reader::readBuffer()
372 {
373     return hasNext() ? const_cast<uint8_t const*>(mData->at(mRp)) : NULL;
374 }
375 
376 size_t
currentToRead()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
hasNext()385 EncodedBuffer::Reader::hasNext()
386 {
387     return mRp.pos() < mData->mWp.pos();
388 }
389 
390 uint8_t
next()391 EncodedBuffer::Reader::next()
392 {
393     uint8_t res = *(mData->at(mRp));
394     mRp.move();
395     return res;
396 }
397 
398 uint64_t
readRawVarint()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
move(size_t amt)412 EncodedBuffer::Reader::move(size_t amt)
413 {
414     mRp.move(amt);
415 }
416 
417 } // util
418 } // android
419