blob: ea9b79a0353f0315a8d7fdb0351caf8fdd7500ed [file] [log] [blame]
Yi Jin974a9c22017-10-02 18:37:08 -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#define LOG_TAG "libprotoutil"
17
Yi Jinfd2a4c72018-04-26 11:49:08 -070018#include <cinttypes>
19#include <type_traits>
Yi Jin00a75442018-03-30 11:01:58 -070020
Yi Jinc5b71ee2018-04-25 16:51:40 -070021#include <android-base/file.h>
Yi Jin974a9c22017-10-02 18:37:08 -070022#include <android/util/protobuf.h>
23#include <android/util/ProtoOutputStream.h>
24#include <cutils/log.h>
Yi Jin974a9c22017-10-02 18:37:08 -070025
26namespace android {
27namespace util {
28
Yi Jin42711a02017-10-11 18:20:24 -070029ProtoOutputStream::ProtoOutputStream()
Joe Onorato99598ee2019-02-11 15:55:13 +000030 :mBuffer(new EncodedBuffer()),
Yi Jin974a9c22017-10-02 18:37:08 -070031 mCopyBegin(0),
32 mCompact(false),
33 mDepth(0),
34 mObjectId(0),
Yi Jin00a75442018-03-30 11:01:58 -070035 mExpectedObjectToken(UINT64_C(-1))
Yi Jin974a9c22017-10-02 18:37:08 -070036{
37}
38
39ProtoOutputStream::~ProtoOutputStream()
40{
41}
42
Yi Jin7f9e63b2018-02-02 16:25:11 -080043
44void
45ProtoOutputStream::clear()
46{
Joe Onorato99598ee2019-02-11 15:55:13 +000047 mBuffer->clear();
Yi Jin7f9e63b2018-02-02 16:25:11 -080048 mCopyBegin = 0;
49 mCompact = false;
50 mDepth = 0;
51 mObjectId = 0;
Yi Jin00a75442018-03-30 11:01:58 -070052 mExpectedObjectToken = UINT64_C(-1);
Yi Jin7f9e63b2018-02-02 16:25:11 -080053}
54
Yi Jinfd2a4c72018-04-26 11:49:08 -070055template<typename T>
Yi Jin974a9c22017-10-02 18:37:08 -070056bool
Yi Jinfd2a4c72018-04-26 11:49:08 -070057ProtoOutputStream::internalWrite(uint64_t fieldId, T val, const char* typeName)
Yi Jin974a9c22017-10-02 18:37:08 -070058{
59 if (mCompact) return false;
60 const uint32_t id = (uint32_t)fieldId;
61 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -070062 case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
63 case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
Yi Jinfd2a4c72018-04-26 11:49:08 -070064 case FIELD_TYPE_INT64: writeInt64Impl(id, (int64_t)val); break;
Yi Jin04625ad2017-10-17 18:29:33 -070065 case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
Yi Jinfd2a4c72018-04-26 11:49:08 -070066 case FIELD_TYPE_INT32: writeInt32Impl(id, (int32_t)val); break;
Yi Jin04625ad2017-10-17 18:29:33 -070067 case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
68 case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
69 case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
Yi Jinfd2a4c72018-04-26 11:49:08 -070070 case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int32_t)val); break;
71 case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (int64_t)val); break;
72 case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int32_t)val); break;
73 case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (int64_t)val); break;
74 case FIELD_TYPE_ENUM:
75 if (std::is_integral<T>::value) {
76 writeEnumImpl(id, (int)val);
77 } else {
78 goto unsupported;
79 }
80 break;
81 case FIELD_TYPE_BOOL:
82 if (std::is_integral<T>::value) {
83 writeBoolImpl(id, val != 0);
84 } else {
85 goto unsupported;
86 }
87 break;
Yi Jin974a9c22017-10-02 18:37:08 -070088 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -070089 goto unsupported;
Yi Jin974a9c22017-10-02 18:37:08 -070090 }
91 return true;
Yi Jinfd2a4c72018-04-26 11:49:08 -070092
93unsupported:
94 ALOGW("Field type %" PRIu64 " is not supported when writing %s val.",
95 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT, typeName);
96 return false;
Yi Jin974a9c22017-10-02 18:37:08 -070097}
98
99bool
Yi Jinfd2a4c72018-04-26 11:49:08 -0700100ProtoOutputStream::write(uint64_t fieldId, double val)
101{
102 return internalWrite(fieldId, val, "double");
103}
104
105
106bool
Yi Jin974a9c22017-10-02 18:37:08 -0700107ProtoOutputStream::write(uint64_t fieldId, float val)
108{
Yi Jinfd2a4c72018-04-26 11:49:08 -0700109 return internalWrite(fieldId, val, "float");
Yi Jin974a9c22017-10-02 18:37:08 -0700110}
111
112bool
113ProtoOutputStream::write(uint64_t fieldId, int val)
114{
Yi Jinfd2a4c72018-04-26 11:49:08 -0700115 return internalWrite(fieldId, val, "int");
Yi Jin974a9c22017-10-02 18:37:08 -0700116}
117
118bool
Colin Crossd013a882018-10-26 13:04:41 -0700119ProtoOutputStream::write(uint64_t fieldId, long val)
120{
121 if (mCompact) return false;
122 const uint32_t id = (uint32_t)fieldId;
123 switch (fieldId & FIELD_TYPE_MASK) {
124 case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
125 case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
126 case FIELD_TYPE_INT64: writeInt64Impl(id, (long long)val); break;
127 case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
128 case FIELD_TYPE_INT32: writeInt32Impl(id, (int)val); break;
129 case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
130 case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
131 case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
132 case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
133 case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
134 case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
135 case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
136 case FIELD_TYPE_ENUM: writeEnumImpl(id, (int)val); break;
137 case FIELD_TYPE_BOOL: writeBoolImpl(id, val != 0); break;
138 default:
139 ALOGW("Field type %d is not supported when writing long val.",
140 (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
141 return false;
142 }
143 return true;
144}
145
146bool
Yi Jin974a9c22017-10-02 18:37:08 -0700147ProtoOutputStream::write(uint64_t fieldId, long long val)
148{
Yi Jinfd2a4c72018-04-26 11:49:08 -0700149 return internalWrite(fieldId, val, "long long");
Yi Jin974a9c22017-10-02 18:37:08 -0700150}
151
152bool
153ProtoOutputStream::write(uint64_t fieldId, bool val)
154{
155 if (mCompact) return false;
156 const uint32_t id = (uint32_t)fieldId;
157 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700158 case FIELD_TYPE_BOOL:
Yi Jin974a9c22017-10-02 18:37:08 -0700159 writeBoolImpl(id, val);
160 return true;
161 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700162 ALOGW("Field type %" PRIu64 " is not supported when writing bool val.",
163 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700164 return false;
165 }
166}
167
168bool
Yi Jin6cacbcb2018-03-30 14:04:52 -0700169ProtoOutputStream::write(uint64_t fieldId, std::string val)
Yi Jin974a9c22017-10-02 18:37:08 -0700170{
171 if (mCompact) return false;
172 const uint32_t id = (uint32_t)fieldId;
173 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700174 case FIELD_TYPE_STRING:
Yi Jin974a9c22017-10-02 18:37:08 -0700175 writeUtf8StringImpl(id, val.c_str(), val.size());
176 return true;
177 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700178 ALOGW("Field type %" PRIu64 " is not supported when writing string val.",
179 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700180 return false;
181 }
182}
183
184bool
Yi Jine0833302017-10-23 15:42:44 -0700185ProtoOutputStream::write(uint64_t fieldId, const char* val, size_t size)
Yi Jin974a9c22017-10-02 18:37:08 -0700186{
187 if (mCompact) return false;
188 const uint32_t id = (uint32_t)fieldId;
Yi Jin974a9c22017-10-02 18:37:08 -0700189 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700190 case FIELD_TYPE_STRING:
191 case FIELD_TYPE_BYTES:
Yi Jin974a9c22017-10-02 18:37:08 -0700192 writeUtf8StringImpl(id, val, size);
193 return true;
Yi Jin04625ad2017-10-17 18:29:33 -0700194 case FIELD_TYPE_MESSAGE:
Yi Jin8ad19382017-10-30 16:07:20 -0700195 // can directly write valid format of message bytes into ProtoOutputStream without calling start/end
196 writeMessageBytesImpl(id, val, size);
197 return true;
Yi Jin974a9c22017-10-02 18:37:08 -0700198 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700199 ALOGW("Field type %" PRIu64 " is not supported when writing char[] val.",
200 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700201 return false;
202 }
203}
204
205/**
206 * Make a token.
207 * Bits 61-63 - tag size (So we can go backwards later if the object had not data)
208 * - 3 bits, max value 7, max value needed 5
209 * Bit 60 - true if the object is repeated
210 * Bits 59-51 - depth (For error checking)
Yi Jin00a75442018-03-30 11:01:58 -0700211 * - 9 bits, max value 511, when checking, value is masked (if we really
212 * are more than 511 levels deep)
Yi Jin974a9c22017-10-02 18:37:08 -0700213 * Bits 32-50 - objectId (For error checking)
Yi Jin00a75442018-03-30 11:01:58 -0700214 * - 19 bits, max value 524,287. that's a lot of objects. IDs will wrap
Yi Jin974a9c22017-10-02 18:37:08 -0700215 * because of the overflow, and only the tokens are compared.
216 * Bits 0-31 - offset of the first size field in the buffer.
217 */
Yi Jin00a75442018-03-30 11:01:58 -0700218static uint64_t
219makeToken(uint32_t tagSize, bool repeated, uint32_t depth, uint32_t objectId, size_t sizePos) {
220 return ((UINT64_C(0x07) & (uint64_t)tagSize) << 61)
221 | (repeated ? (UINT64_C(1) << 60) : 0)
222 | (UINT64_C(0x01ff) & (uint64_t)depth) << 51
223 | (UINT64_C(0x07ffff) & (uint64_t)objectId) << 32
224 | (UINT64_C(0x0ffffffff) & (uint64_t)sizePos);
Yi Jin974a9c22017-10-02 18:37:08 -0700225}
226
227/**
228 * Get the encoded tag size from the token.
229 */
Yi Jin00a75442018-03-30 11:01:58 -0700230static uint32_t getTagSizeFromToken(uint64_t token) {
231 return 0x7 & (token >> 61);
Yi Jin974a9c22017-10-02 18:37:08 -0700232}
233
234/**
235 * Get the nesting depth of startObject calls from the token.
236 */
Yi Jin00a75442018-03-30 11:01:58 -0700237static uint32_t getDepthFromToken(uint64_t token) {
238 return 0x01ff & (token >> 51);
Yi Jin974a9c22017-10-02 18:37:08 -0700239}
240
241/**
242 * Get the location of the childRawSize (the first 32 bit size field) in this object.
243 */
Yi Jin00a75442018-03-30 11:01:58 -0700244static uint32_t getSizePosFromToken(uint64_t token) {
245 return (uint32_t)token;
Yi Jin974a9c22017-10-02 18:37:08 -0700246}
247
Yi Jin5ee07872018-03-05 18:18:27 -0800248uint64_t
Yi Jin974a9c22017-10-02 18:37:08 -0700249ProtoOutputStream::start(uint64_t fieldId)
250{
Yi Jin04625ad2017-10-17 18:29:33 -0700251 if ((fieldId & FIELD_TYPE_MASK) != FIELD_TYPE_MESSAGE) {
Yi Jin00a75442018-03-30 11:01:58 -0700252 ALOGE("Can't call start for non-message type field: 0x%" PRIx64, fieldId);
Yi Jin974a9c22017-10-02 18:37:08 -0700253 return 0;
254 }
255
256 uint32_t id = (uint32_t)fieldId;
Joe Onorato99598ee2019-02-11 15:55:13 +0000257 size_t prevPos = mBuffer->wp()->pos();
258 mBuffer->writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
259 size_t sizePos = mBuffer->wp()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700260
261 mDepth++;
262 mObjectId++;
Joe Onorato99598ee2019-02-11 15:55:13 +0000263 mBuffer->writeRawFixed64(mExpectedObjectToken); // push previous token into stack.
Yi Jin974a9c22017-10-02 18:37:08 -0700264
Yi Jin295d9b12018-02-02 14:33:20 -0800265 mExpectedObjectToken = makeToken(sizePos - prevPos,
Yi Jin974a9c22017-10-02 18:37:08 -0700266 (bool)(fieldId & FIELD_COUNT_REPEATED), mDepth, mObjectId, sizePos);
267 return mExpectedObjectToken;
268}
269
270void
Yi Jin5ee07872018-03-05 18:18:27 -0800271ProtoOutputStream::end(uint64_t token)
Yi Jin974a9c22017-10-02 18:37:08 -0700272{
273 if (token != mExpectedObjectToken) {
Yi Jin00a75442018-03-30 11:01:58 -0700274 ALOGE("Unexpected token: 0x%" PRIx64 ", should be 0x%" PRIx64, token, mExpectedObjectToken);
Yi Jin18678bd2018-04-27 11:51:13 -0700275 mDepth = UINT32_C(-1); // make depth invalid
Yi Jin974a9c22017-10-02 18:37:08 -0700276 return;
277 }
278
Yi Jin00a75442018-03-30 11:01:58 -0700279 uint32_t depth = getDepthFromToken(token);
Yi Jin974a9c22017-10-02 18:37:08 -0700280 if (depth != (mDepth & 0x01ff)) {
Yi Jin00a75442018-03-30 11:01:58 -0700281 ALOGE("Unexpected depth: %" PRIu32 ", should be %" PRIu32, depth, mDepth);
Yi Jin18678bd2018-04-27 11:51:13 -0700282 mDepth = UINT32_C(-1); // make depth invalid
Yi Jin974a9c22017-10-02 18:37:08 -0700283 return;
284 }
285 mDepth--;
286
Yi Jin00a75442018-03-30 11:01:58 -0700287 uint32_t sizePos = getSizePosFromToken(token);
Yi Jin974a9c22017-10-02 18:37:08 -0700288 // number of bytes written in this start-end session.
Joe Onorato99598ee2019-02-11 15:55:13 +0000289 int childRawSize = mBuffer->wp()->pos() - sizePos - 8;
Yi Jin974a9c22017-10-02 18:37:08 -0700290
291 // retrieve the old token from stack.
Joe Onorato99598ee2019-02-11 15:55:13 +0000292 mBuffer->ep()->rewind()->move(sizePos);
293 mExpectedObjectToken = mBuffer->readRawFixed64();
Yi Jin974a9c22017-10-02 18:37:08 -0700294
295 // If raw size is larger than 0, write the negative value here to indicate a compact is needed.
296 if (childRawSize > 0) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000297 mBuffer->editRawFixed32(sizePos, -childRawSize);
298 mBuffer->editRawFixed32(sizePos+4, -1);
Yi Jin974a9c22017-10-02 18:37:08 -0700299 } else {
300 // reset wp which erase the header tag of the message when its size is 0.
Joe Onorato99598ee2019-02-11 15:55:13 +0000301 mBuffer->wp()->rewind()->move(sizePos - getTagSizeFromToken(token));
Yi Jin974a9c22017-10-02 18:37:08 -0700302 }
303}
304
Yi Jin0abdfb02017-11-16 15:32:27 -0800305size_t
306ProtoOutputStream::bytesWritten()
307{
Joe Onorato99598ee2019-02-11 15:55:13 +0000308 return mBuffer->size();
Yi Jin0abdfb02017-11-16 15:32:27 -0800309}
310
Yi Jin974a9c22017-10-02 18:37:08 -0700311bool
312ProtoOutputStream::compact() {
313 if (mCompact) return true;
314 if (mDepth != 0) {
Yi Jin18678bd2018-04-27 11:51:13 -0700315 ALOGE("Can't compact when depth(%" PRIu32 ") is not zero. Missing or extra calls to end.", mDepth);
Yi Jin974a9c22017-10-02 18:37:08 -0700316 return false;
317 }
318 // record the size of the original buffer.
Joe Onorato99598ee2019-02-11 15:55:13 +0000319 size_t rawBufferSize = mBuffer->size();
Yi Jin974a9c22017-10-02 18:37:08 -0700320 if (rawBufferSize == 0) return true; // nothing to do if the buffer is empty;
321
322 // reset edit pointer and recursively compute encoded size of messages.
Joe Onorato99598ee2019-02-11 15:55:13 +0000323 mBuffer->ep()->rewind();
Yi Jin974a9c22017-10-02 18:37:08 -0700324 if (editEncodedSize(rawBufferSize) == 0) {
325 ALOGE("Failed to editEncodedSize.");
326 return false;
327 }
328
329 // reset both edit pointer and write pointer, and compact recursively.
Joe Onorato99598ee2019-02-11 15:55:13 +0000330 mBuffer->ep()->rewind();
331 mBuffer->wp()->rewind();
Yi Jin974a9c22017-10-02 18:37:08 -0700332 if (!compactSize(rawBufferSize)) {
333 ALOGE("Failed to compactSize.");
334 return false;
335 }
336 // copy the reset to the buffer.
337 if (mCopyBegin < rawBufferSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000338 mBuffer->copy(mCopyBegin, rawBufferSize - mCopyBegin);
Yi Jin974a9c22017-10-02 18:37:08 -0700339 }
340
341 // mark true means it is not legal to write to this ProtoOutputStream anymore
342 mCompact = true;
343 return true;
344}
345
346/**
347 * First compaction pass. Iterate through the data, and fill in the
348 * nested object sizes so the next pass can compact them.
349 */
350size_t
351ProtoOutputStream::editEncodedSize(size_t rawSize)
352{
Joe Onorato99598ee2019-02-11 15:55:13 +0000353 size_t objectStart = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700354 size_t objectEnd = objectStart + rawSize;
355 size_t encodedSize = 0;
356 int childRawSize, childEncodedSize;
357 size_t childEncodedSizePos;
358
Joe Onorato99598ee2019-02-11 15:55:13 +0000359 while (mBuffer->ep()->pos() < objectEnd) {
360 uint32_t tag = (uint32_t)mBuffer->readRawVarint();
Yi Jin974a9c22017-10-02 18:37:08 -0700361 encodedSize += get_varint_size(tag);
362 switch (read_wire_type(tag)) {
363 case WIRE_TYPE_VARINT:
364 do {
365 encodedSize++;
Joe Onorato99598ee2019-02-11 15:55:13 +0000366 } while ((mBuffer->readRawByte() & 0x80) != 0);
Yi Jin974a9c22017-10-02 18:37:08 -0700367 break;
368 case WIRE_TYPE_FIXED64:
369 encodedSize += 8;
Joe Onorato99598ee2019-02-11 15:55:13 +0000370 mBuffer->ep()->move(8);
Yi Jin974a9c22017-10-02 18:37:08 -0700371 break;
372 case WIRE_TYPE_LENGTH_DELIMITED:
Joe Onorato99598ee2019-02-11 15:55:13 +0000373 childRawSize = (int)mBuffer->readRawFixed32();
374 childEncodedSizePos = mBuffer->ep()->pos();
375 childEncodedSize = (int)mBuffer->readRawFixed32();
Yi Jin974a9c22017-10-02 18:37:08 -0700376 if (childRawSize >= 0 && childRawSize == childEncodedSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000377 mBuffer->ep()->move(childRawSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700378 } else if (childRawSize < 0 && childEncodedSize == -1){
379 childEncodedSize = editEncodedSize(-childRawSize);
Joe Onorato99598ee2019-02-11 15:55:13 +0000380 mBuffer->editRawFixed32(childEncodedSizePos, childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700381 } else {
382 ALOGE("Bad raw or encoded values: raw=%d, encoded=%d at %zu",
383 childRawSize, childEncodedSize, childEncodedSizePos);
384 return 0;
385 }
386 encodedSize += get_varint_size(childEncodedSize) + childEncodedSize;
387 break;
388 case WIRE_TYPE_FIXED32:
389 encodedSize += 4;
Joe Onorato99598ee2019-02-11 15:55:13 +0000390 mBuffer->ep()->move(4);
Yi Jin974a9c22017-10-02 18:37:08 -0700391 break;
392 default:
393 ALOGE("Unexpected wire type %d in editEncodedSize at [%zu, %zu]",
394 read_wire_type(tag), objectStart, objectEnd);
395 return 0;
396 }
397 }
398 return encodedSize;
399}
400
401/**
402 * Second compaction pass. Iterate through the data, and copy the data
403 * forward in the buffer, converting the pairs of uint32s into a single
404 * unsigned varint of the size.
405 */
406bool
407ProtoOutputStream::compactSize(size_t rawSize)
408{
Joe Onorato99598ee2019-02-11 15:55:13 +0000409 size_t objectStart = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700410 size_t objectEnd = objectStart + rawSize;
411 int childRawSize, childEncodedSize;
412
Joe Onorato99598ee2019-02-11 15:55:13 +0000413 while (mBuffer->ep()->pos() < objectEnd) {
414 uint32_t tag = (uint32_t)mBuffer->readRawVarint();
Yi Jin974a9c22017-10-02 18:37:08 -0700415 switch (read_wire_type(tag)) {
416 case WIRE_TYPE_VARINT:
Joe Onorato99598ee2019-02-11 15:55:13 +0000417 while ((mBuffer->readRawByte() & 0x80) != 0) {}
Yi Jin974a9c22017-10-02 18:37:08 -0700418 break;
419 case WIRE_TYPE_FIXED64:
Joe Onorato99598ee2019-02-11 15:55:13 +0000420 mBuffer->ep()->move(8);
Yi Jin974a9c22017-10-02 18:37:08 -0700421 break;
422 case WIRE_TYPE_LENGTH_DELIMITED:
Joe Onorato99598ee2019-02-11 15:55:13 +0000423 mBuffer->copy(mCopyBegin, mBuffer->ep()->pos() - mCopyBegin);
Yi Jin974a9c22017-10-02 18:37:08 -0700424
Joe Onorato99598ee2019-02-11 15:55:13 +0000425 childRawSize = (int)mBuffer->readRawFixed32();
426 childEncodedSize = (int)mBuffer->readRawFixed32();
427 mCopyBegin = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700428
429 // write encoded size to buffer.
Joe Onorato99598ee2019-02-11 15:55:13 +0000430 mBuffer->writeRawVarint32(childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700431 if (childRawSize >= 0 && childRawSize == childEncodedSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000432 mBuffer->ep()->move(childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700433 } else if (childRawSize < 0){
434 if (!compactSize(-childRawSize)) return false;
435 } else {
436 ALOGE("Bad raw or encoded values: raw=%d, encoded=%d",
437 childRawSize, childEncodedSize);
438 return false;
439 }
440 break;
441 case WIRE_TYPE_FIXED32:
Joe Onorato99598ee2019-02-11 15:55:13 +0000442 mBuffer->ep()->move(4);
Yi Jin974a9c22017-10-02 18:37:08 -0700443 break;
444 default:
445 ALOGE("Unexpected wire type %d in compactSize at [%zu, %zu]",
446 read_wire_type(tag), objectStart, objectEnd);
447 return false;
448 }
449 }
450 return true;
451}
452
Yi Jin42711a02017-10-11 18:20:24 -0700453size_t
454ProtoOutputStream::size()
455{
Yi Jin00a75442018-03-30 11:01:58 -0700456 if (!compact()) {
457 ALOGE("compact failed, the ProtoOutputStream data is corrupted!");
Yi Jin18678bd2018-04-27 11:51:13 -0700458 return 0;
Yi Jin00a75442018-03-30 11:01:58 -0700459 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000460 return mBuffer->size();
Yi Jin42711a02017-10-11 18:20:24 -0700461}
462
Yi Jin974a9c22017-10-02 18:37:08 -0700463bool
Yi Jin42711a02017-10-11 18:20:24 -0700464ProtoOutputStream::flush(int fd)
Yi Jin974a9c22017-10-02 18:37:08 -0700465{
Yi Jin42711a02017-10-11 18:20:24 -0700466 if (fd < 0) return false;
Yi Jin974a9c22017-10-02 18:37:08 -0700467 if (!compact()) return false;
468
Joe Onorato99598ee2019-02-11 15:55:13 +0000469 sp<ProtoReader> reader = mBuffer->read();
470 while (reader->readBuffer() != NULL) {
471 if (!android::base::WriteFully(fd, reader->readBuffer(), reader->currentToRead())) {
472 return false;
473 }
474 reader->move(reader->currentToRead());
Yi Jin974a9c22017-10-02 18:37:08 -0700475 }
476 return true;
477}
478
Tej Singhf53d4452019-05-09 18:17:59 -0700479bool
480ProtoOutputStream::serializeToString(std::string* out)
481{
482 if (out == nullptr) return false;
483 if (!compact()) return false;
484
Tej Singhf53d4452019-05-09 18:17:59 -0700485 sp<ProtoReader> reader = mBuffer->read();
486 out->reserve(reader->size());
487 while (reader->hasNext()) {
488 out->append(static_cast<const char*>(static_cast<const void*>(reader->readBuffer())),
489 reader->currentToRead());
490 reader->move(reader->currentToRead());
491 }
492 return true;
493}
494
Joe Onoratodcd64522019-05-19 17:35:08 -0700495bool
496ProtoOutputStream::serializeToVector(std::vector<uint8_t>* out)
497{
498 if (out == nullptr) return false;
499 if (!compact()) return false;
500
501 sp<ProtoReader> reader = mBuffer->read();
502 out->reserve(reader->size());
503 while (reader->hasNext()) {
504 const uint8_t* buf = reader->readBuffer();
505 size_t size = reader->currentToRead();
506 out->insert(out->end(), buf, buf + size);
507 reader->move(size);
508 }
509 return true;
510}
511
Joe Onorato99598ee2019-02-11 15:55:13 +0000512sp<ProtoReader>
Yi Jin42711a02017-10-11 18:20:24 -0700513ProtoOutputStream::data()
514{
Yi Jin00a75442018-03-30 11:01:58 -0700515 if (!compact()) {
516 ALOGE("compact failed, the ProtoOutputStream data is corrupted!");
Joe Onorato99598ee2019-02-11 15:55:13 +0000517 mBuffer->clear();
Yi Jin00a75442018-03-30 11:01:58 -0700518 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000519 return mBuffer->read();
Yi Jin42711a02017-10-11 18:20:24 -0700520}
521
522void
523ProtoOutputStream::writeRawVarint(uint64_t varint)
524{
Joe Onorato99598ee2019-02-11 15:55:13 +0000525 mBuffer->writeRawVarint64(varint);
Yi Jin42711a02017-10-11 18:20:24 -0700526}
527
528void
529ProtoOutputStream::writeLengthDelimitedHeader(uint32_t id, size_t size)
530{
Joe Onorato99598ee2019-02-11 15:55:13 +0000531 mBuffer->writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
Yi Jin42711a02017-10-11 18:20:24 -0700532 // reserves 64 bits for length delimited fields, if first field is negative, compact it.
Joe Onorato99598ee2019-02-11 15:55:13 +0000533 mBuffer->writeRawFixed32(size);
534 mBuffer->writeRawFixed32(size);
Yi Jin42711a02017-10-11 18:20:24 -0700535}
536
537void
538ProtoOutputStream::writeRawByte(uint8_t byte)
539{
Joe Onorato99598ee2019-02-11 15:55:13 +0000540 mBuffer->writeRawByte(byte);
Yi Jin42711a02017-10-11 18:20:24 -0700541}
542
Yi Jin974a9c22017-10-02 18:37:08 -0700543
544// =========================================================================
545// Private functions
546
547/**
548 * bit_cast
549 */
550template <class From, class To>
551inline To bit_cast(From const &from) {
552 To to;
553 memcpy(&to, &from, sizeof(to));
554 return to;
555}
556
557inline void
558ProtoOutputStream::writeDoubleImpl(uint32_t id, double val)
559{
Joe Onorato99598ee2019-02-11 15:55:13 +0000560 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
561 mBuffer->writeRawFixed64(bit_cast<double, uint64_t>(val));
Yi Jin974a9c22017-10-02 18:37:08 -0700562}
563
564inline void
565ProtoOutputStream::writeFloatImpl(uint32_t id, float val)
566{
Joe Onorato99598ee2019-02-11 15:55:13 +0000567 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
568 mBuffer->writeRawFixed32(bit_cast<float, uint32_t>(val));
Yi Jin974a9c22017-10-02 18:37:08 -0700569}
570
571inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700572ProtoOutputStream::writeInt64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700573{
Joe Onorato99598ee2019-02-11 15:55:13 +0000574 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
575 mBuffer->writeRawVarint64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700576}
577
578inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700579ProtoOutputStream::writeInt32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700580{
Joe Onorato99598ee2019-02-11 15:55:13 +0000581 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
582 mBuffer->writeRawVarint32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700583}
584
585inline void
586ProtoOutputStream::writeUint64Impl(uint32_t id, uint64_t val)
587{
Joe Onorato99598ee2019-02-11 15:55:13 +0000588 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
589 mBuffer->writeRawVarint64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700590}
591
592inline void
593ProtoOutputStream::writeUint32Impl(uint32_t id, uint32_t val)
594{
Joe Onorato99598ee2019-02-11 15:55:13 +0000595 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
596 mBuffer->writeRawVarint32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700597}
598
599inline void
600ProtoOutputStream::writeFixed64Impl(uint32_t id, uint64_t val)
601{
Joe Onorato99598ee2019-02-11 15:55:13 +0000602 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
603 mBuffer->writeRawFixed64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700604}
605
606inline void
607ProtoOutputStream::writeFixed32Impl(uint32_t id, uint32_t val)
608{
Joe Onorato99598ee2019-02-11 15:55:13 +0000609 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
610 mBuffer->writeRawFixed32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700611}
612
613inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700614ProtoOutputStream::writeSFixed64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700615{
Joe Onorato99598ee2019-02-11 15:55:13 +0000616 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
617 mBuffer->writeRawFixed64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700618}
619
620inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700621ProtoOutputStream::writeSFixed32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700622{
Joe Onorato99598ee2019-02-11 15:55:13 +0000623 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
624 mBuffer->writeRawFixed32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700625}
626
627inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700628ProtoOutputStream::writeZigzagInt64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700629{
Joe Onorato99598ee2019-02-11 15:55:13 +0000630 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
631 mBuffer->writeRawVarint64((val << 1) ^ (val >> 63));
Yi Jin974a9c22017-10-02 18:37:08 -0700632}
633
634inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700635ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700636{
Joe Onorato99598ee2019-02-11 15:55:13 +0000637 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
638 mBuffer->writeRawVarint32((val << 1) ^ (val >> 31));
Yi Jin974a9c22017-10-02 18:37:08 -0700639}
640
641inline void
642ProtoOutputStream::writeEnumImpl(uint32_t id, int val)
643{
Joe Onorato99598ee2019-02-11 15:55:13 +0000644 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
645 mBuffer->writeRawVarint32((uint32_t) val);
Yi Jin974a9c22017-10-02 18:37:08 -0700646}
647
648inline void
649ProtoOutputStream::writeBoolImpl(uint32_t id, bool val)
650{
Joe Onorato99598ee2019-02-11 15:55:13 +0000651 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
652 mBuffer->writeRawVarint32(val ? 1 : 0);
Yi Jin974a9c22017-10-02 18:37:08 -0700653}
654
655inline void
656ProtoOutputStream::writeUtf8StringImpl(uint32_t id, const char* val, size_t size)
657{
Yi Jin04625ad2017-10-17 18:29:33 -0700658 if (val == NULL) return;
Yi Jin42711a02017-10-11 18:20:24 -0700659 writeLengthDelimitedHeader(id, size);
Yi Jin974a9c22017-10-02 18:37:08 -0700660 for (size_t i=0; i<size; i++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000661 mBuffer->writeRawByte((uint8_t)val[i]);
Yi Jin974a9c22017-10-02 18:37:08 -0700662 }
663}
664
Yi Jin8ad19382017-10-30 16:07:20 -0700665inline void
666ProtoOutputStream::writeMessageBytesImpl(uint32_t id, const char* val, size_t size)
667{
668 if (val == NULL) return;
669 writeLengthDelimitedHeader(id, size);
670 for (size_t i=0; i<size; i++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000671 mBuffer->writeRawByte(val[i]);
Yi Jin8ad19382017-10-30 16:07:20 -0700672 }
673}
674
Yi Jin974a9c22017-10-02 18:37:08 -0700675} // util
676} // android
677