blob: 435ae88362171ff02033269ae39f8f1c537974bc [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
109/******************************** Write APIs ************************************************/
110size_t
111EncodedBuffer::size() const
112{
113 return mWp.pos();
114}
115
116EncodedBuffer::Pointer*
117EncodedBuffer::wp()
118{
119 return &mWp;
120}
121
122uint8_t*
123EncodedBuffer::writeBuffer()
124{
125 // This prevents write pointer move too fast than allocating the buffer.
126 if (mWp.index() > mBuffers.size()) return NULL;
127 uint8_t* buf = NULL;
128 if (mWp.index() == mBuffers.size()) {
129 buf = (uint8_t*)malloc(mChunkSize);
130
131 if (buf == NULL) return NULL; // This indicates NO_MEMORY
132
133 mBuffers.push_back(buf);
134 }
135 return at(mWp);
136}
137
138size_t
139EncodedBuffer::currentToWrite()
140{
141 return mChunkSize - mWp.offset();
142}
143
Yi Jin974a9c22017-10-02 18:37:08 -0700144void
145EncodedBuffer::writeRawByte(uint8_t val)
146{
147 *writeBuffer() = val;
148 mWp.move();
149}
150
Yi Jinc23fad22017-09-15 17:24:59 -0700151size_t
Yi Jin974a9c22017-10-02 18:37:08 -0700152EncodedBuffer::writeRawVarint64(uint64_t val)
Yi Jinc23fad22017-09-15 17:24:59 -0700153{
154 size_t size = 0;
155 while (true) {
156 size++;
157 if ((val & ~0x7F) == 0) {
Yi Jin974a9c22017-10-02 18:37:08 -0700158 writeRawByte((uint8_t) val);
Yi Jinc23fad22017-09-15 17:24:59 -0700159 return size;
160 } else {
Yi Jin974a9c22017-10-02 18:37:08 -0700161 writeRawByte((uint8_t)((val & 0x7F) | 0x80));
Yi Jinc23fad22017-09-15 17:24:59 -0700162 val >>= 7;
163 }
164 }
165}
166
167size_t
Yi Jin974a9c22017-10-02 18:37:08 -0700168EncodedBuffer::writeRawVarint32(uint32_t val)
169{
170 uint64_t v =(uint64_t)val;
171 return writeRawVarint64(v);
172}
173
174void
175EncodedBuffer::writeRawFixed32(uint32_t val)
176{
177 writeRawByte((uint8_t) val);
178 writeRawByte((uint8_t) (val>>8));
179 writeRawByte((uint8_t) (val>>16));
180 writeRawByte((uint8_t) (val>>24));
181}
182
183void
184EncodedBuffer::writeRawFixed64(uint64_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 writeRawByte((uint8_t) (val>>32));
191 writeRawByte((uint8_t) (val>>40));
192 writeRawByte((uint8_t) (val>>48));
193 writeRawByte((uint8_t) (val>>56));
194}
195
196size_t
Yi Jinc23fad22017-09-15 17:24:59 -0700197EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
198{
Yi Jin974a9c22017-10-02 18:37:08 -0700199 return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
200}
201
202/******************************** Edit APIs ************************************************/
203EncodedBuffer::Pointer*
204EncodedBuffer::ep()
205{
206 return &mEp;
207}
208
209uint8_t
210EncodedBuffer::readRawByte()
211{
212 uint8_t val = *at(mEp);
213 mEp.move();
214 return val;
215}
216
217uint64_t
218EncodedBuffer::readRawVarint()
219{
220 uint64_t val = 0, shift = 0;
221 size_t start = mEp.pos();
222 while (true) {
223 uint8_t byte = readRawByte();
224 val += (byte & 0x7F) << shift;
225 if ((byte & 0x80) == 0) break;
226 shift += 7;
227 }
228 return val;
229}
230
231uint32_t
232EncodedBuffer::readRawFixed32()
233{
234 uint32_t val = 0;
235 for (auto i=0; i<32; i+=8) {
236 val += (uint32_t)readRawByte() << i;
237 }
238 return val;
239}
240
241uint64_t
242EncodedBuffer::readRawFixed64()
243{
244 uint64_t val = 0;
245 for (auto i=0; i<64; i+=8) {
246 val += (uint64_t)readRawByte() << i;
247 }
248 return val;
249}
250
251void
252EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
253{
254 size_t oldPos = mEp.pos();
255 mEp.rewind()->move(pos);
256 for (auto i=0; i<32; i+=8) {
257 *at(mEp) = (uint8_t) (val >> i);
258 mEp.move();
259 }
260 mEp.rewind()->move(oldPos);
261}
262
263void
264EncodedBuffer::copy(size_t srcPos, size_t size)
265{
266 if (size == 0) return;
267 Pointer cp(mChunkSize);
268 cp.move(srcPos);
269
270 while (cp.pos() < srcPos + size) {
271 writeRawByte(*at(cp));
272 cp.move();
273 }
Yi Jinc23fad22017-09-15 17:24:59 -0700274}
275
276/********************************* Read APIs ************************************************/
277EncodedBuffer::iterator
278EncodedBuffer::begin() const
279{
280 return EncodedBuffer::iterator(*this);
281}
282
283EncodedBuffer::iterator::iterator(const EncodedBuffer& buffer)
284 :mData(buffer),
285 mRp(buffer.mChunkSize)
286{
287}
288
289size_t
290EncodedBuffer::iterator::size() const
291{
292 return mData.size();
293}
294
295size_t
296EncodedBuffer::iterator::bytesRead() const
297{
298 return mRp.pos();
299}
300
301EncodedBuffer::Pointer*
302EncodedBuffer::iterator::rp()
303{
304 return &mRp;
305}
306
307uint8_t const*
308EncodedBuffer::iterator::readBuffer()
309{
310 return hasNext() ? const_cast<uint8_t const*>(mData.at(mRp)) : NULL;
311}
312
313size_t
314EncodedBuffer::iterator::currentToRead()
315{
316 return (mData.mWp.index() > mRp.index()) ?
317 mData.mChunkSize - mRp.offset() :
318 mData.mWp.offset() - mRp.offset();
319}
320
321bool
322EncodedBuffer::iterator::hasNext()
323{
324 return mRp.pos() < mData.mWp.pos();
325}
326
327uint8_t
328EncodedBuffer::iterator::next()
329{
330 uint8_t res = *(mData.at(mRp));
331 mRp.move();
332 return res;
333}
334
Yi Jin974a9c22017-10-02 18:37:08 -0700335uint64_t
Yi Jinc23fad22017-09-15 17:24:59 -0700336EncodedBuffer::iterator::readRawVarint()
337{
Yi Jin974a9c22017-10-02 18:37:08 -0700338 uint64_t val = 0, shift = 0;
Yi Jinc23fad22017-09-15 17:24:59 -0700339 while (true) {
340 uint8_t byte = next();
341 val += (byte & 0x7F) << shift;
342 if ((byte & 0x80) == 0) break;
343 shift += 7;
344 }
345 return val;
346}
347
348} // util
349} // android