blob: 3a5e2e9ef5d0c4f5d385c32f5d395ad1af7279a6 [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 */
16
17#include <android/util/EncodedBuffer.h>
Yi Jin974a9c22017-10-02 18:37:08 -070018#include <android/util/protobuf.h>
Yi Jinc23fad22017-09-15 17:24:59 -070019
20#include <stdlib.h>
21
22namespace android {
23namespace util {
24
25const size_t BUFFER_SIZE = 8 * 1024; // 8 KB
26
27EncodedBuffer::Pointer::Pointer() : Pointer(BUFFER_SIZE)
28{
29}
30
31EncodedBuffer::Pointer::Pointer(size_t chunkSize)
32 :mIndex(0),
33 mOffset(0)
34{
35 mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
36}
37
38size_t
39EncodedBuffer::Pointer::pos() const
40{
41 return mIndex * mChunkSize + mOffset;
42}
43
44size_t
45EncodedBuffer::Pointer::index() const
46{
47 return mIndex;
48}
49
50size_t
51EncodedBuffer::Pointer::offset() const
52{
53 return mOffset;
54}
55
Yi Jin974a9c22017-10-02 18:37:08 -070056EncodedBuffer::Pointer*
Yi Jinc23fad22017-09-15 17:24:59 -070057EncodedBuffer::Pointer::move(size_t amt)
58{
59 size_t newOffset = mOffset + amt;
60 mIndex += newOffset / mChunkSize;
61 mOffset = newOffset % mChunkSize;
Yi Jin974a9c22017-10-02 18:37:08 -070062 return this;
Yi Jinc23fad22017-09-15 17:24:59 -070063}
64
Yi Jin974a9c22017-10-02 18:37:08 -070065EncodedBuffer::Pointer*
Yi Jinc23fad22017-09-15 17:24:59 -070066EncodedBuffer::Pointer::rewind()
67{
68 mIndex = 0;
69 mOffset = 0;
Yi Jin974a9c22017-10-02 18:37:08 -070070 return this;
Yi Jinc23fad22017-09-15 17:24:59 -070071}
72
73EncodedBuffer::Pointer
74EncodedBuffer::Pointer::copy() const
75{
76 Pointer p = Pointer(mChunkSize);
77 p.mIndex = mIndex;
78 p.mOffset = mOffset;
79 return p;
80}
81
82// ===========================================================
83EncodedBuffer::EncodedBuffer() : EncodedBuffer(0)
84{
85}
86
87EncodedBuffer::EncodedBuffer(size_t chunkSize)
88 :mBuffers()
89{
90 mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
91 mWp = Pointer(mChunkSize);
Yi Jin974a9c22017-10-02 18:37:08 -070092 mEp = Pointer(mChunkSize);
Yi Jinc23fad22017-09-15 17:24:59 -070093}
94
95EncodedBuffer::~EncodedBuffer()
96{
97 for (size_t i=0; i<mBuffers.size(); i++) {
98 uint8_t* buf = mBuffers[i];
99 free(buf);
100 }
101}
102
103inline uint8_t*
104EncodedBuffer::at(const Pointer& p) const
105{
106 return mBuffers[p.index()] + p.offset();
107}
108
Yi Jin7f9e63b2018-02-02 16:25:11 -0800109void
110EncodedBuffer::clear()
111{
112 mWp.rewind();
113 mEp.rewind();
114}
115
Yi Jinc23fad22017-09-15 17:24:59 -0700116/******************************** Write APIs ************************************************/
117size_t
118EncodedBuffer::size() const
119{
120 return mWp.pos();
121}
122
123EncodedBuffer::Pointer*
124EncodedBuffer::wp()
125{
126 return &mWp;
127}
128
129uint8_t*
130EncodedBuffer::writeBuffer()
131{
132 // This prevents write pointer move too fast than allocating the buffer.
133 if (mWp.index() > mBuffers.size()) return NULL;
134 uint8_t* buf = NULL;
135 if (mWp.index() == mBuffers.size()) {
136 buf = (uint8_t*)malloc(mChunkSize);
137
138 if (buf == NULL) return NULL; // This indicates NO_MEMORY
139
140 mBuffers.push_back(buf);
141 }
142 return at(mWp);
143}
144
145size_t
146EncodedBuffer::currentToWrite()
147{
148 return mChunkSize - mWp.offset();
149}
150
Yi Jin974a9c22017-10-02 18:37:08 -0700151void
152EncodedBuffer::writeRawByte(uint8_t val)
153{
154 *writeBuffer() = val;
155 mWp.move();
156}
157
Yi Jinc23fad22017-09-15 17:24:59 -0700158size_t
Yi Jin974a9c22017-10-02 18:37:08 -0700159EncodedBuffer::writeRawVarint64(uint64_t val)
Yi Jinc23fad22017-09-15 17:24:59 -0700160{
161 size_t size = 0;
162 while (true) {
163 size++;
164 if ((val & ~0x7F) == 0) {
Yi Jin974a9c22017-10-02 18:37:08 -0700165 writeRawByte((uint8_t) val);
Yi Jinc23fad22017-09-15 17:24:59 -0700166 return size;
167 } else {
Yi Jin974a9c22017-10-02 18:37:08 -0700168 writeRawByte((uint8_t)((val & 0x7F) | 0x80));
Yi Jinc23fad22017-09-15 17:24:59 -0700169 val >>= 7;
170 }
171 }
172}
173
174size_t
Yi Jin974a9c22017-10-02 18:37:08 -0700175EncodedBuffer::writeRawVarint32(uint32_t val)
176{
177 uint64_t v =(uint64_t)val;
178 return writeRawVarint64(v);
179}
180
181void
182EncodedBuffer::writeRawFixed32(uint32_t val)
183{
184 writeRawByte((uint8_t) val);
185 writeRawByte((uint8_t) (val>>8));
186 writeRawByte((uint8_t) (val>>16));
187 writeRawByte((uint8_t) (val>>24));
188}
189
190void
191EncodedBuffer::writeRawFixed64(uint64_t val)
192{
193 writeRawByte((uint8_t) val);
194 writeRawByte((uint8_t) (val>>8));
195 writeRawByte((uint8_t) (val>>16));
196 writeRawByte((uint8_t) (val>>24));
197 writeRawByte((uint8_t) (val>>32));
198 writeRawByte((uint8_t) (val>>40));
199 writeRawByte((uint8_t) (val>>48));
200 writeRawByte((uint8_t) (val>>56));
201}
202
203size_t
Yi Jinc23fad22017-09-15 17:24:59 -0700204EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
205{
Yi Jin974a9c22017-10-02 18:37:08 -0700206 return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
207}
208
209/******************************** Edit APIs ************************************************/
210EncodedBuffer::Pointer*
211EncodedBuffer::ep()
212{
213 return &mEp;
214}
215
216uint8_t
217EncodedBuffer::readRawByte()
218{
219 uint8_t val = *at(mEp);
220 mEp.move();
221 return val;
222}
223
224uint64_t
225EncodedBuffer::readRawVarint()
226{
227 uint64_t val = 0, shift = 0;
228 size_t start = mEp.pos();
229 while (true) {
230 uint8_t byte = readRawByte();
231 val += (byte & 0x7F) << shift;
232 if ((byte & 0x80) == 0) break;
233 shift += 7;
234 }
235 return val;
236}
237
238uint32_t
239EncodedBuffer::readRawFixed32()
240{
241 uint32_t val = 0;
242 for (auto i=0; i<32; i+=8) {
243 val += (uint32_t)readRawByte() << i;
244 }
245 return val;
246}
247
248uint64_t
249EncodedBuffer::readRawFixed64()
250{
251 uint64_t val = 0;
252 for (auto i=0; i<64; i+=8) {
253 val += (uint64_t)readRawByte() << i;
254 }
255 return val;
256}
257
258void
259EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
260{
261 size_t oldPos = mEp.pos();
262 mEp.rewind()->move(pos);
263 for (auto i=0; i<32; i+=8) {
264 *at(mEp) = (uint8_t) (val >> i);
265 mEp.move();
266 }
267 mEp.rewind()->move(oldPos);
268}
269
270void
271EncodedBuffer::copy(size_t srcPos, size_t size)
272{
273 if (size == 0) return;
274 Pointer cp(mChunkSize);
275 cp.move(srcPos);
276
277 while (cp.pos() < srcPos + size) {
278 writeRawByte(*at(cp));
279 cp.move();
280 }
Yi Jinc23fad22017-09-15 17:24:59 -0700281}
282
283/********************************* Read APIs ************************************************/
284EncodedBuffer::iterator
285EncodedBuffer::begin() const
286{
287 return EncodedBuffer::iterator(*this);
288}
289
290EncodedBuffer::iterator::iterator(const EncodedBuffer& buffer)
291 :mData(buffer),
292 mRp(buffer.mChunkSize)
293{
294}
295
296size_t
297EncodedBuffer::iterator::size() const
298{
299 return mData.size();
300}
301
302size_t
303EncodedBuffer::iterator::bytesRead() const
304{
305 return mRp.pos();
306}
307
308EncodedBuffer::Pointer*
309EncodedBuffer::iterator::rp()
310{
311 return &mRp;
312}
313
314uint8_t const*
315EncodedBuffer::iterator::readBuffer()
316{
317 return hasNext() ? const_cast<uint8_t const*>(mData.at(mRp)) : NULL;
318}
319
320size_t
321EncodedBuffer::iterator::currentToRead()
322{
323 return (mData.mWp.index() > mRp.index()) ?
324 mData.mChunkSize - mRp.offset() :
325 mData.mWp.offset() - mRp.offset();
326}
327
328bool
329EncodedBuffer::iterator::hasNext()
330{
331 return mRp.pos() < mData.mWp.pos();
332}
333
334uint8_t
335EncodedBuffer::iterator::next()
336{
337 uint8_t res = *(mData.at(mRp));
338 mRp.move();
339 return res;
340}
341
Yi Jin974a9c22017-10-02 18:37:08 -0700342uint64_t
Yi Jinc23fad22017-09-15 17:24:59 -0700343EncodedBuffer::iterator::readRawVarint()
344{
Yi Jin974a9c22017-10-02 18:37:08 -0700345 uint64_t val = 0, shift = 0;
Yi Jinc23fad22017-09-15 17:24:59 -0700346 while (true) {
347 uint8_t byte = next();
348 val += (byte & 0x7F) << shift;
349 if ((byte & 0x80) == 0) break;
350 shift += 7;
351 }
352 return val;
353}
354
355} // util
356} // android