xref: /aosp_15_r20/frameworks/base/libs/protoutil/src/EncodedBuffer.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker #define LOG_TAG "libprotoutil"
17*d57664e9SAndroid Build Coastguard Worker 
18*d57664e9SAndroid Build Coastguard Worker #include <stdlib.h>
19*d57664e9SAndroid Build Coastguard Worker #include <sys/mman.h>
20*d57664e9SAndroid Build Coastguard Worker #include <unistd.h>
21*d57664e9SAndroid Build Coastguard Worker 
22*d57664e9SAndroid Build Coastguard Worker #include <android/util/EncodedBuffer.h>
23*d57664e9SAndroid Build Coastguard Worker #include <android/util/protobuf.h>
24*d57664e9SAndroid Build Coastguard Worker #include <cutils/log.h>
25*d57664e9SAndroid Build Coastguard Worker 
26*d57664e9SAndroid Build Coastguard Worker namespace android {
27*d57664e9SAndroid Build Coastguard Worker namespace util {
28*d57664e9SAndroid Build Coastguard Worker 
29*d57664e9SAndroid Build Coastguard Worker constexpr size_t BUFFER_SIZE = 8 * 1024; // 8 KB
30*d57664e9SAndroid Build Coastguard Worker const size_t kPageSize = getpagesize();
31*d57664e9SAndroid Build Coastguard Worker 
Pointer()32*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::Pointer() : Pointer(BUFFER_SIZE)
33*d57664e9SAndroid Build Coastguard Worker {
34*d57664e9SAndroid Build Coastguard Worker }
35*d57664e9SAndroid Build Coastguard Worker 
Pointer(size_t chunkSize)36*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::Pointer(size_t chunkSize)
37*d57664e9SAndroid Build Coastguard Worker         :mIndex(0),
38*d57664e9SAndroid Build Coastguard Worker          mOffset(0)
39*d57664e9SAndroid Build Coastguard Worker {
40*d57664e9SAndroid Build Coastguard Worker     mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
41*d57664e9SAndroid Build Coastguard Worker }
42*d57664e9SAndroid Build Coastguard Worker 
43*d57664e9SAndroid Build Coastguard Worker size_t
pos() const44*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::pos() const
45*d57664e9SAndroid Build Coastguard Worker {
46*d57664e9SAndroid Build Coastguard Worker     return mIndex * mChunkSize + mOffset;
47*d57664e9SAndroid Build Coastguard Worker }
48*d57664e9SAndroid Build Coastguard Worker 
49*d57664e9SAndroid Build Coastguard Worker size_t
index() const50*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::index() const
51*d57664e9SAndroid Build Coastguard Worker {
52*d57664e9SAndroid Build Coastguard Worker     return mIndex;
53*d57664e9SAndroid Build Coastguard Worker }
54*d57664e9SAndroid Build Coastguard Worker 
55*d57664e9SAndroid Build Coastguard Worker size_t
offset() const56*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::offset() const
57*d57664e9SAndroid Build Coastguard Worker {
58*d57664e9SAndroid Build Coastguard Worker     return mOffset;
59*d57664e9SAndroid Build Coastguard Worker }
60*d57664e9SAndroid Build Coastguard Worker 
61*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer*
move(size_t amt)62*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::move(size_t amt)
63*d57664e9SAndroid Build Coastguard Worker {
64*d57664e9SAndroid Build Coastguard Worker     size_t newOffset = mOffset + amt;
65*d57664e9SAndroid Build Coastguard Worker     mIndex += newOffset / mChunkSize;
66*d57664e9SAndroid Build Coastguard Worker     mOffset = newOffset % mChunkSize;
67*d57664e9SAndroid Build Coastguard Worker     return this;
68*d57664e9SAndroid Build Coastguard Worker }
69*d57664e9SAndroid Build Coastguard Worker 
70*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer*
rewind()71*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::rewind()
72*d57664e9SAndroid Build Coastguard Worker {
73*d57664e9SAndroid Build Coastguard Worker     mIndex = 0;
74*d57664e9SAndroid Build Coastguard Worker     mOffset = 0;
75*d57664e9SAndroid Build Coastguard Worker     return this;
76*d57664e9SAndroid Build Coastguard Worker }
77*d57664e9SAndroid Build Coastguard Worker 
78*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer
copy() const79*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer::copy() const
80*d57664e9SAndroid Build Coastguard Worker {
81*d57664e9SAndroid Build Coastguard Worker     Pointer p = Pointer(mChunkSize);
82*d57664e9SAndroid Build Coastguard Worker     p.mIndex = mIndex;
83*d57664e9SAndroid Build Coastguard Worker     p.mOffset = mOffset;
84*d57664e9SAndroid Build Coastguard Worker     return p;
85*d57664e9SAndroid Build Coastguard Worker }
86*d57664e9SAndroid Build Coastguard Worker 
87*d57664e9SAndroid Build Coastguard Worker // ===========================================================
EncodedBuffer()88*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::EncodedBuffer() : EncodedBuffer(BUFFER_SIZE)
89*d57664e9SAndroid Build Coastguard Worker {
90*d57664e9SAndroid Build Coastguard Worker }
91*d57664e9SAndroid Build Coastguard Worker 
EncodedBuffer(size_t chunkSize)92*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::EncodedBuffer(size_t chunkSize)
93*d57664e9SAndroid Build Coastguard Worker         :mBuffers()
94*d57664e9SAndroid Build Coastguard Worker {
95*d57664e9SAndroid Build Coastguard Worker     // Align chunkSize to memory page size
96*d57664e9SAndroid Build Coastguard Worker     chunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
97*d57664e9SAndroid Build Coastguard Worker     mChunkSize = (chunkSize + (kPageSize - 1)) & ~(kPageSize - 1);
98*d57664e9SAndroid Build Coastguard Worker     mWp = Pointer(mChunkSize);
99*d57664e9SAndroid Build Coastguard Worker     mEp = Pointer(mChunkSize);
100*d57664e9SAndroid Build Coastguard Worker }
101*d57664e9SAndroid Build Coastguard Worker 
~EncodedBuffer()102*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::~EncodedBuffer()
103*d57664e9SAndroid Build Coastguard Worker {
104*d57664e9SAndroid Build Coastguard Worker     for (size_t i=0; i<mBuffers.size(); i++) {
105*d57664e9SAndroid Build Coastguard Worker         uint8_t* buf = mBuffers[i];
106*d57664e9SAndroid Build Coastguard Worker         munmap(buf, mChunkSize);
107*d57664e9SAndroid Build Coastguard Worker     }
108*d57664e9SAndroid Build Coastguard Worker }
109*d57664e9SAndroid Build Coastguard Worker 
110*d57664e9SAndroid Build Coastguard Worker inline uint8_t*
at(const Pointer & p) const111*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::at(const Pointer& p) const
112*d57664e9SAndroid Build Coastguard Worker {
113*d57664e9SAndroid Build Coastguard Worker     return mBuffers[p.index()] + p.offset();
114*d57664e9SAndroid Build Coastguard Worker }
115*d57664e9SAndroid Build Coastguard Worker 
116*d57664e9SAndroid Build Coastguard Worker void
clear()117*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::clear()
118*d57664e9SAndroid Build Coastguard Worker {
119*d57664e9SAndroid Build Coastguard Worker     mWp.rewind();
120*d57664e9SAndroid Build Coastguard Worker     mEp.rewind();
121*d57664e9SAndroid Build Coastguard Worker }
122*d57664e9SAndroid Build Coastguard Worker 
123*d57664e9SAndroid Build Coastguard Worker /******************************** Write APIs ************************************************/
124*d57664e9SAndroid Build Coastguard Worker size_t
size() const125*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::size() const
126*d57664e9SAndroid Build Coastguard Worker {
127*d57664e9SAndroid Build Coastguard Worker     return mWp.pos();
128*d57664e9SAndroid Build Coastguard Worker }
129*d57664e9SAndroid Build Coastguard Worker 
130*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer*
wp()131*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::wp()
132*d57664e9SAndroid Build Coastguard Worker {
133*d57664e9SAndroid Build Coastguard Worker     return &mWp;
134*d57664e9SAndroid Build Coastguard Worker }
135*d57664e9SAndroid Build Coastguard Worker 
136*d57664e9SAndroid Build Coastguard Worker uint8_t*
writeBuffer()137*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeBuffer()
138*d57664e9SAndroid Build Coastguard Worker {
139*d57664e9SAndroid Build Coastguard Worker     // This prevents write pointer move too fast than allocating the buffer.
140*d57664e9SAndroid Build Coastguard Worker     if (mWp.index() > mBuffers.size()) return NULL;
141*d57664e9SAndroid Build Coastguard Worker     uint8_t* buf = NULL;
142*d57664e9SAndroid Build Coastguard Worker     if (mWp.index() == mBuffers.size()) {
143*d57664e9SAndroid Build Coastguard Worker         // Use mmap instead of malloc to ensure memory alignment i.e. no fragmentation so that
144*d57664e9SAndroid Build Coastguard Worker         // the mem region can be immediately reused by the allocator after calling munmap()
145*d57664e9SAndroid Build Coastguard Worker         buf = (uint8_t*)mmap(NULL, mChunkSize, PROT_READ | PROT_WRITE,
146*d57664e9SAndroid Build Coastguard Worker                 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
147*d57664e9SAndroid Build Coastguard Worker 
148*d57664e9SAndroid Build Coastguard Worker         if (buf == NULL) return NULL; // This indicates NO_MEMORY
149*d57664e9SAndroid Build Coastguard Worker 
150*d57664e9SAndroid Build Coastguard Worker         mBuffers.push_back(buf);
151*d57664e9SAndroid Build Coastguard Worker     }
152*d57664e9SAndroid Build Coastguard Worker     return at(mWp);
153*d57664e9SAndroid Build Coastguard Worker }
154*d57664e9SAndroid Build Coastguard Worker 
155*d57664e9SAndroid Build Coastguard Worker size_t
currentToWrite()156*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::currentToWrite()
157*d57664e9SAndroid Build Coastguard Worker {
158*d57664e9SAndroid Build Coastguard Worker     return mChunkSize - mWp.offset();
159*d57664e9SAndroid Build Coastguard Worker }
160*d57664e9SAndroid Build Coastguard Worker 
161*d57664e9SAndroid Build Coastguard Worker void
writeRawByte(uint8_t val)162*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRawByte(uint8_t val)
163*d57664e9SAndroid Build Coastguard Worker {
164*d57664e9SAndroid Build Coastguard Worker     *writeBuffer() = val;
165*d57664e9SAndroid Build Coastguard Worker     mWp.move();
166*d57664e9SAndroid Build Coastguard Worker }
167*d57664e9SAndroid Build Coastguard Worker 
168*d57664e9SAndroid Build Coastguard Worker size_t
writeRawVarint64(uint64_t val)169*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRawVarint64(uint64_t val)
170*d57664e9SAndroid Build Coastguard Worker {
171*d57664e9SAndroid Build Coastguard Worker     size_t size = 0;
172*d57664e9SAndroid Build Coastguard Worker     while (true) {
173*d57664e9SAndroid Build Coastguard Worker         size++;
174*d57664e9SAndroid Build Coastguard Worker         if ((val & ~0x7F) == 0) {
175*d57664e9SAndroid Build Coastguard Worker             writeRawByte((uint8_t) val);
176*d57664e9SAndroid Build Coastguard Worker             return size;
177*d57664e9SAndroid Build Coastguard Worker         } else {
178*d57664e9SAndroid Build Coastguard Worker             writeRawByte((uint8_t)((val & 0x7F) | 0x80));
179*d57664e9SAndroid Build Coastguard Worker             val >>= 7;
180*d57664e9SAndroid Build Coastguard Worker         }
181*d57664e9SAndroid Build Coastguard Worker     }
182*d57664e9SAndroid Build Coastguard Worker }
183*d57664e9SAndroid Build Coastguard Worker 
184*d57664e9SAndroid Build Coastguard Worker size_t
writeRawVarint32(uint32_t val)185*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRawVarint32(uint32_t val)
186*d57664e9SAndroid Build Coastguard Worker {
187*d57664e9SAndroid Build Coastguard Worker     uint64_t v =(uint64_t)val;
188*d57664e9SAndroid Build Coastguard Worker     return writeRawVarint64(v);
189*d57664e9SAndroid Build Coastguard Worker }
190*d57664e9SAndroid Build Coastguard Worker 
191*d57664e9SAndroid Build Coastguard Worker void
writeRawFixed32(uint32_t val)192*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRawFixed32(uint32_t val)
193*d57664e9SAndroid Build Coastguard Worker {
194*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) val);
195*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>8));
196*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>16));
197*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>24));
198*d57664e9SAndroid Build Coastguard Worker }
199*d57664e9SAndroid Build Coastguard Worker 
200*d57664e9SAndroid Build Coastguard Worker void
writeRawFixed64(uint64_t val)201*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRawFixed64(uint64_t val)
202*d57664e9SAndroid Build Coastguard Worker {
203*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) val);
204*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>8));
205*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>16));
206*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>24));
207*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>32));
208*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>40));
209*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>48));
210*d57664e9SAndroid Build Coastguard Worker     writeRawByte((uint8_t) (val>>56));
211*d57664e9SAndroid Build Coastguard Worker }
212*d57664e9SAndroid Build Coastguard Worker 
213*d57664e9SAndroid Build Coastguard Worker size_t
writeHeader(uint32_t fieldId,uint8_t wireType)214*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
215*d57664e9SAndroid Build Coastguard Worker {
216*d57664e9SAndroid Build Coastguard Worker     return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
217*d57664e9SAndroid Build Coastguard Worker }
218*d57664e9SAndroid Build Coastguard Worker 
219*d57664e9SAndroid Build Coastguard Worker status_t
writeRaw(uint8_t const * buf,size_t size)220*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRaw(uint8_t const* buf, size_t size)
221*d57664e9SAndroid Build Coastguard Worker {
222*d57664e9SAndroid Build Coastguard Worker     while (size > 0) {
223*d57664e9SAndroid Build Coastguard Worker         uint8_t* target = writeBuffer();
224*d57664e9SAndroid Build Coastguard Worker         if (target == NULL) {
225*d57664e9SAndroid Build Coastguard Worker             return -ENOMEM;
226*d57664e9SAndroid Build Coastguard Worker         }
227*d57664e9SAndroid Build Coastguard Worker         size_t chunk = currentToWrite();
228*d57664e9SAndroid Build Coastguard Worker         if (chunk > size) {
229*d57664e9SAndroid Build Coastguard Worker             chunk = size;
230*d57664e9SAndroid Build Coastguard Worker         }
231*d57664e9SAndroid Build Coastguard Worker         memcpy(target, buf, chunk);
232*d57664e9SAndroid Build Coastguard Worker         size -= chunk;
233*d57664e9SAndroid Build Coastguard Worker         buf += chunk;
234*d57664e9SAndroid Build Coastguard Worker         mWp.move(chunk);
235*d57664e9SAndroid Build Coastguard Worker     }
236*d57664e9SAndroid Build Coastguard Worker     return NO_ERROR;
237*d57664e9SAndroid Build Coastguard Worker }
238*d57664e9SAndroid Build Coastguard Worker 
239*d57664e9SAndroid Build Coastguard Worker status_t
writeRaw(const sp<ProtoReader> & reader)240*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRaw(const sp<ProtoReader>& reader)
241*d57664e9SAndroid Build Coastguard Worker {
242*d57664e9SAndroid Build Coastguard Worker     status_t err;
243*d57664e9SAndroid Build Coastguard Worker     uint8_t const* buf;
244*d57664e9SAndroid Build Coastguard Worker     while ((buf = reader->readBuffer()) != nullptr) {
245*d57664e9SAndroid Build Coastguard Worker         size_t amt = reader->currentToRead();
246*d57664e9SAndroid Build Coastguard Worker         err = writeRaw(buf, amt);
247*d57664e9SAndroid Build Coastguard Worker         reader->move(amt);
248*d57664e9SAndroid Build Coastguard Worker         if (err != NO_ERROR) {
249*d57664e9SAndroid Build Coastguard Worker             return err;
250*d57664e9SAndroid Build Coastguard Worker         }
251*d57664e9SAndroid Build Coastguard Worker     }
252*d57664e9SAndroid Build Coastguard Worker     return NO_ERROR;
253*d57664e9SAndroid Build Coastguard Worker }
254*d57664e9SAndroid Build Coastguard Worker 
255*d57664e9SAndroid Build Coastguard Worker status_t
writeRaw(const sp<ProtoReader> & reader,size_t size)256*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::writeRaw(const sp<ProtoReader>& reader, size_t size)
257*d57664e9SAndroid Build Coastguard Worker {
258*d57664e9SAndroid Build Coastguard Worker     status_t err;
259*d57664e9SAndroid Build Coastguard Worker     uint8_t const* buf;
260*d57664e9SAndroid Build Coastguard Worker     while (size > 0 && (buf = reader->readBuffer()) != nullptr) {
261*d57664e9SAndroid Build Coastguard Worker         size_t amt = reader->currentToRead();
262*d57664e9SAndroid Build Coastguard Worker         if (size < amt) {
263*d57664e9SAndroid Build Coastguard Worker             amt = size;
264*d57664e9SAndroid Build Coastguard Worker         }
265*d57664e9SAndroid Build Coastguard Worker         err = writeRaw(buf, amt);
266*d57664e9SAndroid Build Coastguard Worker         reader->move(amt);
267*d57664e9SAndroid Build Coastguard Worker         size -= amt;
268*d57664e9SAndroid Build Coastguard Worker         if (err != NO_ERROR) {
269*d57664e9SAndroid Build Coastguard Worker             return err;
270*d57664e9SAndroid Build Coastguard Worker         }
271*d57664e9SAndroid Build Coastguard Worker     }
272*d57664e9SAndroid Build Coastguard Worker     return size == 0 ? NO_ERROR : NOT_ENOUGH_DATA;
273*d57664e9SAndroid Build Coastguard Worker }
274*d57664e9SAndroid Build Coastguard Worker 
275*d57664e9SAndroid Build Coastguard Worker 
276*d57664e9SAndroid Build Coastguard Worker /******************************** Edit APIs ************************************************/
277*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Pointer*
ep()278*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::ep()
279*d57664e9SAndroid Build Coastguard Worker {
280*d57664e9SAndroid Build Coastguard Worker     return &mEp;
281*d57664e9SAndroid Build Coastguard Worker }
282*d57664e9SAndroid Build Coastguard Worker 
283*d57664e9SAndroid Build Coastguard Worker uint8_t
readRawByte()284*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::readRawByte()
285*d57664e9SAndroid Build Coastguard Worker {
286*d57664e9SAndroid Build Coastguard Worker     uint8_t val = *at(mEp);
287*d57664e9SAndroid Build Coastguard Worker     mEp.move();
288*d57664e9SAndroid Build Coastguard Worker     return val;
289*d57664e9SAndroid Build Coastguard Worker }
290*d57664e9SAndroid Build Coastguard Worker 
291*d57664e9SAndroid Build Coastguard Worker uint64_t
readRawVarint()292*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::readRawVarint()
293*d57664e9SAndroid Build Coastguard Worker {
294*d57664e9SAndroid Build Coastguard Worker     uint64_t val = 0, shift = 0;
295*d57664e9SAndroid Build Coastguard Worker     size_t start = mEp.pos();
296*d57664e9SAndroid Build Coastguard Worker     while (true) {
297*d57664e9SAndroid Build Coastguard Worker         uint8_t byte = readRawByte();
298*d57664e9SAndroid Build Coastguard Worker         val |= (UINT64_C(0x7F) & byte) << shift;
299*d57664e9SAndroid Build Coastguard Worker         if ((byte & 0x80) == 0) break;
300*d57664e9SAndroid Build Coastguard Worker         shift += 7;
301*d57664e9SAndroid Build Coastguard Worker     }
302*d57664e9SAndroid Build Coastguard Worker     return val;
303*d57664e9SAndroid Build Coastguard Worker }
304*d57664e9SAndroid Build Coastguard Worker 
305*d57664e9SAndroid Build Coastguard Worker uint32_t
readRawFixed32()306*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::readRawFixed32()
307*d57664e9SAndroid Build Coastguard Worker {
308*d57664e9SAndroid Build Coastguard Worker     uint32_t val = 0;
309*d57664e9SAndroid Build Coastguard Worker     for (auto i=0; i<32; i+=8) {
310*d57664e9SAndroid Build Coastguard Worker         val += (uint32_t)readRawByte() << i;
311*d57664e9SAndroid Build Coastguard Worker     }
312*d57664e9SAndroid Build Coastguard Worker     return val;
313*d57664e9SAndroid Build Coastguard Worker }
314*d57664e9SAndroid Build Coastguard Worker 
315*d57664e9SAndroid Build Coastguard Worker uint64_t
readRawFixed64()316*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::readRawFixed64()
317*d57664e9SAndroid Build Coastguard Worker {
318*d57664e9SAndroid Build Coastguard Worker     uint64_t val = 0;
319*d57664e9SAndroid Build Coastguard Worker     for (auto i=0; i<64; i+=8) {
320*d57664e9SAndroid Build Coastguard Worker         val += (uint64_t)readRawByte() << i;
321*d57664e9SAndroid Build Coastguard Worker     }
322*d57664e9SAndroid Build Coastguard Worker     return val;
323*d57664e9SAndroid Build Coastguard Worker }
324*d57664e9SAndroid Build Coastguard Worker 
325*d57664e9SAndroid Build Coastguard Worker void
editRawFixed32(size_t pos,uint32_t val)326*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
327*d57664e9SAndroid Build Coastguard Worker {
328*d57664e9SAndroid Build Coastguard Worker     size_t oldPos = mEp.pos();
329*d57664e9SAndroid Build Coastguard Worker     mEp.rewind()->move(pos);
330*d57664e9SAndroid Build Coastguard Worker     for (auto i=0; i<32; i+=8) {
331*d57664e9SAndroid Build Coastguard Worker         *at(mEp) = (uint8_t) (val >> i);
332*d57664e9SAndroid Build Coastguard Worker         mEp.move();
333*d57664e9SAndroid Build Coastguard Worker     }
334*d57664e9SAndroid Build Coastguard Worker     mEp.rewind()->move(oldPos);
335*d57664e9SAndroid Build Coastguard Worker }
336*d57664e9SAndroid Build Coastguard Worker 
337*d57664e9SAndroid Build Coastguard Worker void
copy(size_t srcPos,size_t size)338*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::copy(size_t srcPos, size_t size)
339*d57664e9SAndroid Build Coastguard Worker {
340*d57664e9SAndroid Build Coastguard Worker     if (size == 0) return;
341*d57664e9SAndroid Build Coastguard Worker     Pointer cp(mChunkSize);
342*d57664e9SAndroid Build Coastguard Worker     cp.move(srcPos);
343*d57664e9SAndroid Build Coastguard Worker 
344*d57664e9SAndroid Build Coastguard Worker     while (cp.pos() < srcPos + size) {
345*d57664e9SAndroid Build Coastguard Worker         writeRawByte(*at(cp));
346*d57664e9SAndroid Build Coastguard Worker         cp.move();
347*d57664e9SAndroid Build Coastguard Worker     }
348*d57664e9SAndroid Build Coastguard Worker }
349*d57664e9SAndroid Build Coastguard Worker 
350*d57664e9SAndroid Build Coastguard Worker /********************************* Read APIs ************************************************/
351*d57664e9SAndroid Build Coastguard Worker sp<ProtoReader>
read()352*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::read()
353*d57664e9SAndroid Build Coastguard Worker {
354*d57664e9SAndroid Build Coastguard Worker     return new EncodedBuffer::Reader(this);
355*d57664e9SAndroid Build Coastguard Worker }
356*d57664e9SAndroid Build Coastguard Worker 
Reader(const sp<EncodedBuffer> & buffer)357*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::Reader(const sp<EncodedBuffer>& buffer)
358*d57664e9SAndroid Build Coastguard Worker         :mData(buffer),
359*d57664e9SAndroid Build Coastguard Worker          mRp(buffer->mChunkSize)
360*d57664e9SAndroid Build Coastguard Worker {
361*d57664e9SAndroid Build Coastguard Worker }
362*d57664e9SAndroid Build Coastguard Worker 
~Reader()363*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::~Reader() {
364*d57664e9SAndroid Build Coastguard Worker }
365*d57664e9SAndroid Build Coastguard Worker 
366*d57664e9SAndroid Build Coastguard Worker ssize_t
size() const367*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::size() const
368*d57664e9SAndroid Build Coastguard Worker {
369*d57664e9SAndroid Build Coastguard Worker     return (ssize_t)mData->size();
370*d57664e9SAndroid Build Coastguard Worker }
371*d57664e9SAndroid Build Coastguard Worker 
372*d57664e9SAndroid Build Coastguard Worker size_t
bytesRead() const373*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::bytesRead() const
374*d57664e9SAndroid Build Coastguard Worker {
375*d57664e9SAndroid Build Coastguard Worker     return mRp.pos();
376*d57664e9SAndroid Build Coastguard Worker }
377*d57664e9SAndroid Build Coastguard Worker 
378*d57664e9SAndroid Build Coastguard Worker uint8_t const*
readBuffer()379*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::readBuffer()
380*d57664e9SAndroid Build Coastguard Worker {
381*d57664e9SAndroid Build Coastguard Worker     return hasNext() ? const_cast<uint8_t const*>(mData->at(mRp)) : NULL;
382*d57664e9SAndroid Build Coastguard Worker }
383*d57664e9SAndroid Build Coastguard Worker 
384*d57664e9SAndroid Build Coastguard Worker size_t
currentToRead()385*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::currentToRead()
386*d57664e9SAndroid Build Coastguard Worker {
387*d57664e9SAndroid Build Coastguard Worker     return (mData->mWp.index() > mRp.index()) ?
388*d57664e9SAndroid Build Coastguard Worker             mData->mChunkSize - mRp.offset() :
389*d57664e9SAndroid Build Coastguard Worker             mData->mWp.offset() - mRp.offset();
390*d57664e9SAndroid Build Coastguard Worker }
391*d57664e9SAndroid Build Coastguard Worker 
392*d57664e9SAndroid Build Coastguard Worker bool
hasNext()393*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::hasNext()
394*d57664e9SAndroid Build Coastguard Worker {
395*d57664e9SAndroid Build Coastguard Worker     return mRp.pos() < mData->mWp.pos();
396*d57664e9SAndroid Build Coastguard Worker }
397*d57664e9SAndroid Build Coastguard Worker 
398*d57664e9SAndroid Build Coastguard Worker uint8_t
next()399*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::next()
400*d57664e9SAndroid Build Coastguard Worker {
401*d57664e9SAndroid Build Coastguard Worker     uint8_t res = *(mData->at(mRp));
402*d57664e9SAndroid Build Coastguard Worker     mRp.move();
403*d57664e9SAndroid Build Coastguard Worker     return res;
404*d57664e9SAndroid Build Coastguard Worker }
405*d57664e9SAndroid Build Coastguard Worker 
406*d57664e9SAndroid Build Coastguard Worker uint64_t
readRawVarint()407*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::readRawVarint()
408*d57664e9SAndroid Build Coastguard Worker {
409*d57664e9SAndroid Build Coastguard Worker     uint64_t val = 0, shift = 0;
410*d57664e9SAndroid Build Coastguard Worker     while (true) {
411*d57664e9SAndroid Build Coastguard Worker         uint8_t byte = next();
412*d57664e9SAndroid Build Coastguard Worker         val |= (INT64_C(0x7F) & byte) << shift;
413*d57664e9SAndroid Build Coastguard Worker         if ((byte & 0x80) == 0) break;
414*d57664e9SAndroid Build Coastguard Worker         shift += 7;
415*d57664e9SAndroid Build Coastguard Worker     }
416*d57664e9SAndroid Build Coastguard Worker     return val;
417*d57664e9SAndroid Build Coastguard Worker }
418*d57664e9SAndroid Build Coastguard Worker 
419*d57664e9SAndroid Build Coastguard Worker void
move(size_t amt)420*d57664e9SAndroid Build Coastguard Worker EncodedBuffer::Reader::move(size_t amt)
421*d57664e9SAndroid Build Coastguard Worker {
422*d57664e9SAndroid Build Coastguard Worker     mRp.move(amt);
423*d57664e9SAndroid Build Coastguard Worker }
424*d57664e9SAndroid Build Coastguard Worker 
425*d57664e9SAndroid Build Coastguard Worker } // util
426*d57664e9SAndroid Build Coastguard Worker } // android
427