blob: 96b54c63a836b970a3c80daa2846d9160db1780a [file] [log] [blame]
Yi Jinc23fad22017-09-15 17:24:59 -07001/*
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 */
Yi Jinad3e6e52018-04-03 15:10:34 -070016#define LOG_TAG "libprotoutil"
17
18#include <stdlib.h>
Mike Ma892ccd92020-03-20 16:30:37 -070019#include <sys/mman.h>
Yi Jinc23fad22017-09-15 17:24:59 -070020
21#include <android/util/EncodedBuffer.h>
Yi Jin974a9c22017-10-02 18:37:08 -070022#include <android/util/protobuf.h>
Yi Jinad3e6e52018-04-03 15:10:34 -070023#include <cutils/log.h>
Yi Jinc23fad22017-09-15 17:24:59 -070024
25namespace android {
26namespace util {
27
28const size_t BUFFER_SIZE = 8 * 1024; // 8 KB
29
30EncodedBuffer::Pointer::Pointer() : Pointer(BUFFER_SIZE)
31{
32}
33
34EncodedBuffer::Pointer::Pointer(size_t chunkSize)
35 :mIndex(0),
36 mOffset(0)
37{
38 mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
39}
40
41size_t
42EncodedBuffer::Pointer::pos() const
43{
44 return mIndex * mChunkSize + mOffset;
45}
46
47size_t
48EncodedBuffer::Pointer::index() const
49{
50 return mIndex;
51}
52
53size_t
54EncodedBuffer::Pointer::offset() const
55{
56 return mOffset;
57}
58
Yi Jin974a9c22017-10-02 18:37:08 -070059EncodedBuffer::Pointer*
Yi Jinc23fad22017-09-15 17:24:59 -070060EncodedBuffer::Pointer::move(size_t amt)
61{
62 size_t newOffset = mOffset + amt;
63 mIndex += newOffset / mChunkSize;
64 mOffset = newOffset % mChunkSize;
Yi Jin974a9c22017-10-02 18:37:08 -070065 return this;
Yi Jinc23fad22017-09-15 17:24:59 -070066}
67
Yi Jin974a9c22017-10-02 18:37:08 -070068EncodedBuffer::Pointer*
Yi Jinc23fad22017-09-15 17:24:59 -070069EncodedBuffer::Pointer::rewind()
70{
71 mIndex = 0;
72 mOffset = 0;
Yi Jin974a9c22017-10-02 18:37:08 -070073 return this;
Yi Jinc23fad22017-09-15 17:24:59 -070074}
75
76EncodedBuffer::Pointer
77EncodedBuffer::Pointer::copy() const
78{
79 Pointer p = Pointer(mChunkSize);
80 p.mIndex = mIndex;
81 p.mOffset = mOffset;
82 return p;
83}
84
85// ===========================================================
Mike Ma892ccd92020-03-20 16:30:37 -070086EncodedBuffer::EncodedBuffer() : EncodedBuffer(BUFFER_SIZE)
Yi Jinc23fad22017-09-15 17:24:59 -070087{
88}
89
90EncodedBuffer::EncodedBuffer(size_t chunkSize)
91 :mBuffers()
92{
Mike Ma892ccd92020-03-20 16:30:37 -070093 // Align chunkSize to memory page size
94 chunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
95 mChunkSize = (chunkSize / PAGE_SIZE + ((chunkSize % PAGE_SIZE == 0) ? 0 : 1)) * PAGE_SIZE;
Yi Jinc23fad22017-09-15 17:24:59 -070096 mWp = Pointer(mChunkSize);
Yi Jin974a9c22017-10-02 18:37:08 -070097 mEp = Pointer(mChunkSize);
Yi Jinc23fad22017-09-15 17:24:59 -070098}
99
100EncodedBuffer::~EncodedBuffer()
101{
102 for (size_t i=0; i<mBuffers.size(); i++) {
103 uint8_t* buf = mBuffers[i];
Mike Ma892ccd92020-03-20 16:30:37 -0700104 munmap(buf, mChunkSize);
Yi Jinc23fad22017-09-15 17:24:59 -0700105 }
106}
107
108inline uint8_t*
109EncodedBuffer::at(const Pointer& p) const
110{
111 return mBuffers[p.index()] + p.offset();
112}
113
Yi Jin7f9e63b2018-02-02 16:25:11 -0800114void
115EncodedBuffer::clear()
116{
117 mWp.rewind();
118 mEp.rewind();
119}
120
Yi Jinc23fad22017-09-15 17:24:59 -0700121/******************************** Write APIs ************************************************/
122size_t
123EncodedBuffer::size() const
124{
125 return mWp.pos();
126}
127
128EncodedBuffer::Pointer*
129EncodedBuffer::wp()
130{
131 return &mWp;
132}
133
134uint8_t*
135EncodedBuffer::writeBuffer()
136{
137 // This prevents write pointer move too fast than allocating the buffer.
138 if (mWp.index() > mBuffers.size()) return NULL;
139 uint8_t* buf = NULL;
140 if (mWp.index() == mBuffers.size()) {
Mike Ma892ccd92020-03-20 16:30:37 -0700141 // Use mmap instead of malloc to ensure memory alignment i.e. no fragmentation so that
142 // the mem region can be immediately reused by the allocator after calling munmap()
143 buf = (uint8_t*)mmap(NULL, mChunkSize, PROT_READ | PROT_WRITE,
144 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
Yi Jinc23fad22017-09-15 17:24:59 -0700145
146 if (buf == NULL) return NULL; // This indicates NO_MEMORY
147
148 mBuffers.push_back(buf);
149 }
150 return at(mWp);
151}
152
153size_t
154EncodedBuffer::currentToWrite()
155{
156 return mChunkSize - mWp.offset();
157}
158
Yi Jin974a9c22017-10-02 18:37:08 -0700159void
160EncodedBuffer::writeRawByte(uint8_t val)
161{
162 *writeBuffer() = val;
163 mWp.move();
164}
165
Yi Jinc23fad22017-09-15 17:24:59 -0700166size_t
Yi Jin974a9c22017-10-02 18:37:08 -0700167EncodedBuffer::writeRawVarint64(uint64_t val)
Yi Jinc23fad22017-09-15 17:24:59 -0700168{
169 size_t size = 0;
170 while (true) {
171 size++;
172 if ((val & ~0x7F) == 0) {
Yi Jin974a9c22017-10-02 18:37:08 -0700173 writeRawByte((uint8_t) val);
Yi Jinc23fad22017-09-15 17:24:59 -0700174 return size;
175 } else {
Yi Jin974a9c22017-10-02 18:37:08 -0700176 writeRawByte((uint8_t)((val & 0x7F) | 0x80));
Yi Jinc23fad22017-09-15 17:24:59 -0700177 val >>= 7;
178 }
179 }
180}
181
182size_t
Yi Jin974a9c22017-10-02 18:37:08 -0700183EncodedBuffer::writeRawVarint32(uint32_t val)
184{
185 uint64_t v =(uint64_t)val;
186 return writeRawVarint64(v);
187}
188
189void
190EncodedBuffer::writeRawFixed32(uint32_t val)
191{
192 writeRawByte((uint8_t) val);
193 writeRawByte((uint8_t) (val>>8));
194 writeRawByte((uint8_t) (val>>16));
195 writeRawByte((uint8_t) (val>>24));
196}
197
198void
199EncodedBuffer::writeRawFixed64(uint64_t val)
200{
201 writeRawByte((uint8_t) val);
202 writeRawByte((uint8_t) (val>>8));
203 writeRawByte((uint8_t) (val>>16));
204 writeRawByte((uint8_t) (val>>24));
205 writeRawByte((uint8_t) (val>>32));
206 writeRawByte((uint8_t) (val>>40));
207 writeRawByte((uint8_t) (val>>48));
208 writeRawByte((uint8_t) (val>>56));
209}
210
211size_t
Yi Jinc23fad22017-09-15 17:24:59 -0700212EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
213{
Yi Jin974a9c22017-10-02 18:37:08 -0700214 return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
215}
216
Joe Onorato99598ee2019-02-11 15:55:13 +0000217status_t
218EncodedBuffer::writeRaw(uint8_t const* buf, size_t size)
219{
220 while (size > 0) {
221 uint8_t* target = writeBuffer();
222 if (target == NULL) {
223 return -ENOMEM;
224 }
225 size_t chunk = currentToWrite();
226 if (chunk > size) {
227 chunk = size;
228 }
229 memcpy(target, buf, chunk);
230 size -= chunk;
231 buf += chunk;
232 mWp.move(chunk);
233 }
234 return NO_ERROR;
235}
236
237status_t
238EncodedBuffer::writeRaw(const sp<ProtoReader>& reader)
239{
240 status_t err;
241 uint8_t const* buf;
242 while ((buf = reader->readBuffer()) != nullptr) {
243 size_t amt = reader->currentToRead();
244 err = writeRaw(buf, amt);
245 reader->move(amt);
246 if (err != NO_ERROR) {
247 return err;
248 }
249 }
250 return NO_ERROR;
251}
252
253status_t
254EncodedBuffer::writeRaw(const sp<ProtoReader>& reader, size_t size)
255{
256 status_t err;
257 uint8_t const* buf;
258 while (size > 0 && (buf = reader->readBuffer()) != nullptr) {
259 size_t amt = reader->currentToRead();
260 if (size < amt) {
261 amt = size;
262 }
263 err = writeRaw(buf, amt);
264 reader->move(amt);
265 size -= amt;
266 if (err != NO_ERROR) {
267 return err;
268 }
269 }
270 return size == 0 ? NO_ERROR : NOT_ENOUGH_DATA;
271}
272
273
Yi Jin974a9c22017-10-02 18:37:08 -0700274/******************************** Edit APIs ************************************************/
275EncodedBuffer::Pointer*
276EncodedBuffer::ep()
277{
278 return &mEp;
279}
280
281uint8_t
282EncodedBuffer::readRawByte()
283{
284 uint8_t val = *at(mEp);
285 mEp.move();
286 return val;
287}
288
289uint64_t
290EncodedBuffer::readRawVarint()
291{
292 uint64_t val = 0, shift = 0;
293 size_t start = mEp.pos();
294 while (true) {
295 uint8_t byte = readRawByte();
Yi Jinad3e6e52018-04-03 15:10:34 -0700296 val |= (UINT64_C(0x7F) & byte) << shift;
Yi Jin974a9c22017-10-02 18:37:08 -0700297 if ((byte & 0x80) == 0) break;
298 shift += 7;
299 }
300 return val;
301}
302
303uint32_t
304EncodedBuffer::readRawFixed32()
305{
306 uint32_t val = 0;
307 for (auto i=0; i<32; i+=8) {
308 val += (uint32_t)readRawByte() << i;
309 }
310 return val;
311}
312
313uint64_t
314EncodedBuffer::readRawFixed64()
315{
316 uint64_t val = 0;
317 for (auto i=0; i<64; i+=8) {
318 val += (uint64_t)readRawByte() << i;
319 }
320 return val;
321}
322
323void
324EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
325{
326 size_t oldPos = mEp.pos();
327 mEp.rewind()->move(pos);
328 for (auto i=0; i<32; i+=8) {
329 *at(mEp) = (uint8_t) (val >> i);
330 mEp.move();
331 }
332 mEp.rewind()->move(oldPos);
333}
334
335void
336EncodedBuffer::copy(size_t srcPos, size_t size)
337{
338 if (size == 0) return;
339 Pointer cp(mChunkSize);
340 cp.move(srcPos);
341
342 while (cp.pos() < srcPos + size) {
343 writeRawByte(*at(cp));
344 cp.move();
345 }
Yi Jinc23fad22017-09-15 17:24:59 -0700346}
347
348/********************************* Read APIs ************************************************/
Joe Onorato99598ee2019-02-11 15:55:13 +0000349sp<ProtoReader>
350EncodedBuffer::read()
Yi Jinc23fad22017-09-15 17:24:59 -0700351{
Joe Onorato99598ee2019-02-11 15:55:13 +0000352 return new EncodedBuffer::Reader(this);
Yi Jinc23fad22017-09-15 17:24:59 -0700353}
354
Joe Onorato99598ee2019-02-11 15:55:13 +0000355EncodedBuffer::Reader::Reader(const sp<EncodedBuffer>& buffer)
Yi Jinc23fad22017-09-15 17:24:59 -0700356 :mData(buffer),
Joe Onorato99598ee2019-02-11 15:55:13 +0000357 mRp(buffer->mChunkSize)
Yi Jinc23fad22017-09-15 17:24:59 -0700358{
359}
360
Joe Onorato99598ee2019-02-11 15:55:13 +0000361EncodedBuffer::Reader::~Reader() {
362}
363
364ssize_t
365EncodedBuffer::Reader::size() const
Yi Jinc23fad22017-09-15 17:24:59 -0700366{
Joe Onorato99598ee2019-02-11 15:55:13 +0000367 return (ssize_t)mData->size();
Yi Jinc23fad22017-09-15 17:24:59 -0700368}
369
370size_t
Joe Onorato99598ee2019-02-11 15:55:13 +0000371EncodedBuffer::Reader::bytesRead() const
Yi Jinc23fad22017-09-15 17:24:59 -0700372{
373 return mRp.pos();
374}
375
Yi Jinc23fad22017-09-15 17:24:59 -0700376uint8_t const*
Joe Onorato99598ee2019-02-11 15:55:13 +0000377EncodedBuffer::Reader::readBuffer()
Yi Jinc23fad22017-09-15 17:24:59 -0700378{
Joe Onorato99598ee2019-02-11 15:55:13 +0000379 return hasNext() ? const_cast<uint8_t const*>(mData->at(mRp)) : NULL;
Yi Jinc23fad22017-09-15 17:24:59 -0700380}
381
382size_t
Joe Onorato99598ee2019-02-11 15:55:13 +0000383EncodedBuffer::Reader::currentToRead()
Yi Jinc23fad22017-09-15 17:24:59 -0700384{
Joe Onorato99598ee2019-02-11 15:55:13 +0000385 return (mData->mWp.index() > mRp.index()) ?
386 mData->mChunkSize - mRp.offset() :
387 mData->mWp.offset() - mRp.offset();
Yi Jinc23fad22017-09-15 17:24:59 -0700388}
389
390bool
Joe Onorato99598ee2019-02-11 15:55:13 +0000391EncodedBuffer::Reader::hasNext()
Yi Jinc23fad22017-09-15 17:24:59 -0700392{
Joe Onorato99598ee2019-02-11 15:55:13 +0000393 return mRp.pos() < mData->mWp.pos();
Yi Jinc23fad22017-09-15 17:24:59 -0700394}
395
396uint8_t
Joe Onorato99598ee2019-02-11 15:55:13 +0000397EncodedBuffer::Reader::next()
Yi Jinc23fad22017-09-15 17:24:59 -0700398{
Joe Onorato99598ee2019-02-11 15:55:13 +0000399 uint8_t res = *(mData->at(mRp));
Yi Jinc23fad22017-09-15 17:24:59 -0700400 mRp.move();
401 return res;
402}
403
Yi Jin974a9c22017-10-02 18:37:08 -0700404uint64_t
Joe Onorato99598ee2019-02-11 15:55:13 +0000405EncodedBuffer::Reader::readRawVarint()
Yi Jinc23fad22017-09-15 17:24:59 -0700406{
Yi Jin974a9c22017-10-02 18:37:08 -0700407 uint64_t val = 0, shift = 0;
Yi Jinc23fad22017-09-15 17:24:59 -0700408 while (true) {
409 uint8_t byte = next();
Yi Jinad3e6e52018-04-03 15:10:34 -0700410 val |= (INT64_C(0x7F) & byte) << shift;
Yi Jinc23fad22017-09-15 17:24:59 -0700411 if ((byte & 0x80) == 0) break;
412 shift += 7;
413 }
414 return val;
415}
416
Joe Onorato99598ee2019-02-11 15:55:13 +0000417void
418EncodedBuffer::Reader::move(size_t amt)
419{
420 mRp.move(amt);
421}
422
Yi Jinc23fad22017-09-15 17:24:59 -0700423} // util
424} // android