blob: fcf82eed4eb13a75254a10704c36a99a9c0d1b49 [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
Mike Ma892ccd92020-03-20 16:30:37 -070029ProtoOutputStream::ProtoOutputStream(): ProtoOutputStream(new EncodedBuffer())
30{
31}
32
33ProtoOutputStream::ProtoOutputStream(sp<EncodedBuffer> buffer)
34 :mBuffer(buffer),
Yi Jin974a9c22017-10-02 18:37:08 -070035 mCopyBegin(0),
36 mCompact(false),
37 mDepth(0),
38 mObjectId(0),
Yi Jin00a75442018-03-30 11:01:58 -070039 mExpectedObjectToken(UINT64_C(-1))
Yi Jin974a9c22017-10-02 18:37:08 -070040{
41}
42
43ProtoOutputStream::~ProtoOutputStream()
44{
45}
46
Yi Jin7f9e63b2018-02-02 16:25:11 -080047
48void
49ProtoOutputStream::clear()
50{
Joe Onorato99598ee2019-02-11 15:55:13 +000051 mBuffer->clear();
Yi Jin7f9e63b2018-02-02 16:25:11 -080052 mCopyBegin = 0;
53 mCompact = false;
54 mDepth = 0;
55 mObjectId = 0;
Yi Jin00a75442018-03-30 11:01:58 -070056 mExpectedObjectToken = UINT64_C(-1);
Yi Jin7f9e63b2018-02-02 16:25:11 -080057}
58
Yi Jinfd2a4c72018-04-26 11:49:08 -070059template<typename T>
Yi Jin974a9c22017-10-02 18:37:08 -070060bool
Yi Jinfd2a4c72018-04-26 11:49:08 -070061ProtoOutputStream::internalWrite(uint64_t fieldId, T val, const char* typeName)
Yi Jin974a9c22017-10-02 18:37:08 -070062{
63 if (mCompact) return false;
64 const uint32_t id = (uint32_t)fieldId;
65 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -070066 case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
67 case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
Yi Jinfd2a4c72018-04-26 11:49:08 -070068 case FIELD_TYPE_INT64: writeInt64Impl(id, (int64_t)val); break;
Yi Jin04625ad2017-10-17 18:29:33 -070069 case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
Yi Jinfd2a4c72018-04-26 11:49:08 -070070 case FIELD_TYPE_INT32: writeInt32Impl(id, (int32_t)val); break;
Yi Jin04625ad2017-10-17 18:29:33 -070071 case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
72 case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
73 case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
Yi Jinfd2a4c72018-04-26 11:49:08 -070074 case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int32_t)val); break;
75 case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (int64_t)val); break;
76 case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int32_t)val); break;
77 case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (int64_t)val); break;
78 case FIELD_TYPE_ENUM:
79 if (std::is_integral<T>::value) {
80 writeEnumImpl(id, (int)val);
81 } else {
82 goto unsupported;
83 }
84 break;
85 case FIELD_TYPE_BOOL:
86 if (std::is_integral<T>::value) {
87 writeBoolImpl(id, val != 0);
88 } else {
89 goto unsupported;
90 }
91 break;
Yi Jin974a9c22017-10-02 18:37:08 -070092 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -070093 goto unsupported;
Yi Jin974a9c22017-10-02 18:37:08 -070094 }
95 return true;
Yi Jinfd2a4c72018-04-26 11:49:08 -070096
97unsupported:
98 ALOGW("Field type %" PRIu64 " is not supported when writing %s val.",
99 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT, typeName);
100 return false;
Yi Jin974a9c22017-10-02 18:37:08 -0700101}
102
103bool
Yi Jinfd2a4c72018-04-26 11:49:08 -0700104ProtoOutputStream::write(uint64_t fieldId, double val)
105{
106 return internalWrite(fieldId, val, "double");
107}
108
109
110bool
Yi Jin974a9c22017-10-02 18:37:08 -0700111ProtoOutputStream::write(uint64_t fieldId, float val)
112{
Yi Jinfd2a4c72018-04-26 11:49:08 -0700113 return internalWrite(fieldId, val, "float");
Yi Jin974a9c22017-10-02 18:37:08 -0700114}
115
116bool
117ProtoOutputStream::write(uint64_t fieldId, int val)
118{
Yi Jinfd2a4c72018-04-26 11:49:08 -0700119 return internalWrite(fieldId, val, "int");
Yi Jin974a9c22017-10-02 18:37:08 -0700120}
121
122bool
Colin Crossd013a882018-10-26 13:04:41 -0700123ProtoOutputStream::write(uint64_t fieldId, long val)
124{
125 if (mCompact) return false;
126 const uint32_t id = (uint32_t)fieldId;
127 switch (fieldId & FIELD_TYPE_MASK) {
128 case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
129 case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
130 case FIELD_TYPE_INT64: writeInt64Impl(id, (long long)val); break;
131 case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
132 case FIELD_TYPE_INT32: writeInt32Impl(id, (int)val); break;
133 case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
134 case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
135 case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
136 case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
137 case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
138 case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
139 case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
140 case FIELD_TYPE_ENUM: writeEnumImpl(id, (int)val); break;
141 case FIELD_TYPE_BOOL: writeBoolImpl(id, val != 0); break;
142 default:
143 ALOGW("Field type %d is not supported when writing long val.",
144 (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
145 return false;
146 }
147 return true;
148}
149
150bool
Yi Jin974a9c22017-10-02 18:37:08 -0700151ProtoOutputStream::write(uint64_t fieldId, long long val)
152{
Yi Jinfd2a4c72018-04-26 11:49:08 -0700153 return internalWrite(fieldId, val, "long long");
Yi Jin974a9c22017-10-02 18:37:08 -0700154}
155
156bool
157ProtoOutputStream::write(uint64_t fieldId, bool val)
158{
159 if (mCompact) return false;
160 const uint32_t id = (uint32_t)fieldId;
161 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700162 case FIELD_TYPE_BOOL:
Yi Jin974a9c22017-10-02 18:37:08 -0700163 writeBoolImpl(id, val);
164 return true;
165 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700166 ALOGW("Field type %" PRIu64 " is not supported when writing bool val.",
167 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700168 return false;
169 }
170}
171
172bool
Yi Jin6cacbcb2018-03-30 14:04:52 -0700173ProtoOutputStream::write(uint64_t fieldId, std::string val)
Yi Jin974a9c22017-10-02 18:37:08 -0700174{
175 if (mCompact) return false;
176 const uint32_t id = (uint32_t)fieldId;
177 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700178 case FIELD_TYPE_STRING:
Yi Jin974a9c22017-10-02 18:37:08 -0700179 writeUtf8StringImpl(id, val.c_str(), val.size());
180 return true;
181 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700182 ALOGW("Field type %" PRIu64 " is not supported when writing string val.",
183 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700184 return false;
185 }
186}
187
188bool
Yi Jine0833302017-10-23 15:42:44 -0700189ProtoOutputStream::write(uint64_t fieldId, const char* val, size_t size)
Yi Jin974a9c22017-10-02 18:37:08 -0700190{
191 if (mCompact) return false;
192 const uint32_t id = (uint32_t)fieldId;
Yi Jin974a9c22017-10-02 18:37:08 -0700193 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700194 case FIELD_TYPE_STRING:
195 case FIELD_TYPE_BYTES:
Yi Jin974a9c22017-10-02 18:37:08 -0700196 writeUtf8StringImpl(id, val, size);
197 return true;
Yi Jin04625ad2017-10-17 18:29:33 -0700198 case FIELD_TYPE_MESSAGE:
Yi Jin8ad19382017-10-30 16:07:20 -0700199 // can directly write valid format of message bytes into ProtoOutputStream without calling start/end
200 writeMessageBytesImpl(id, val, size);
201 return true;
Yi Jin974a9c22017-10-02 18:37:08 -0700202 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700203 ALOGW("Field type %" PRIu64 " is not supported when writing char[] val.",
204 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700205 return false;
206 }
207}
208
209/**
210 * Make a token.
211 * Bits 61-63 - tag size (So we can go backwards later if the object had not data)
212 * - 3 bits, max value 7, max value needed 5
213 * Bit 60 - true if the object is repeated
214 * Bits 59-51 - depth (For error checking)
Yi Jin00a75442018-03-30 11:01:58 -0700215 * - 9 bits, max value 511, when checking, value is masked (if we really
216 * are more than 511 levels deep)
Yi Jin974a9c22017-10-02 18:37:08 -0700217 * Bits 32-50 - objectId (For error checking)
Yi Jin00a75442018-03-30 11:01:58 -0700218 * - 19 bits, max value 524,287. that's a lot of objects. IDs will wrap
Yi Jin974a9c22017-10-02 18:37:08 -0700219 * because of the overflow, and only the tokens are compared.
220 * Bits 0-31 - offset of the first size field in the buffer.
221 */
Yi Jin00a75442018-03-30 11:01:58 -0700222static uint64_t
223makeToken(uint32_t tagSize, bool repeated, uint32_t depth, uint32_t objectId, size_t sizePos) {
224 return ((UINT64_C(0x07) & (uint64_t)tagSize) << 61)
225 | (repeated ? (UINT64_C(1) << 60) : 0)
226 | (UINT64_C(0x01ff) & (uint64_t)depth) << 51
227 | (UINT64_C(0x07ffff) & (uint64_t)objectId) << 32
228 | (UINT64_C(0x0ffffffff) & (uint64_t)sizePos);
Yi Jin974a9c22017-10-02 18:37:08 -0700229}
230
231/**
232 * Get the encoded tag size from the token.
233 */
Yi Jin00a75442018-03-30 11:01:58 -0700234static uint32_t getTagSizeFromToken(uint64_t token) {
235 return 0x7 & (token >> 61);
Yi Jin974a9c22017-10-02 18:37:08 -0700236}
237
238/**
239 * Get the nesting depth of startObject calls from the token.
240 */
Yi Jin00a75442018-03-30 11:01:58 -0700241static uint32_t getDepthFromToken(uint64_t token) {
242 return 0x01ff & (token >> 51);
Yi Jin974a9c22017-10-02 18:37:08 -0700243}
244
245/**
246 * Get the location of the childRawSize (the first 32 bit size field) in this object.
247 */
Yi Jin00a75442018-03-30 11:01:58 -0700248static uint32_t getSizePosFromToken(uint64_t token) {
249 return (uint32_t)token;
Yi Jin974a9c22017-10-02 18:37:08 -0700250}
251
Yi Jin5ee07872018-03-05 18:18:27 -0800252uint64_t
Yi Jin974a9c22017-10-02 18:37:08 -0700253ProtoOutputStream::start(uint64_t fieldId)
254{
Yi Jin04625ad2017-10-17 18:29:33 -0700255 if ((fieldId & FIELD_TYPE_MASK) != FIELD_TYPE_MESSAGE) {
Yi Jin00a75442018-03-30 11:01:58 -0700256 ALOGE("Can't call start for non-message type field: 0x%" PRIx64, fieldId);
Yi Jin974a9c22017-10-02 18:37:08 -0700257 return 0;
258 }
259
260 uint32_t id = (uint32_t)fieldId;
Joe Onorato99598ee2019-02-11 15:55:13 +0000261 size_t prevPos = mBuffer->wp()->pos();
262 mBuffer->writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
263 size_t sizePos = mBuffer->wp()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700264
265 mDepth++;
266 mObjectId++;
Joe Onorato99598ee2019-02-11 15:55:13 +0000267 mBuffer->writeRawFixed64(mExpectedObjectToken); // push previous token into stack.
Yi Jin974a9c22017-10-02 18:37:08 -0700268
Yi Jin295d9b12018-02-02 14:33:20 -0800269 mExpectedObjectToken = makeToken(sizePos - prevPos,
Yi Jin974a9c22017-10-02 18:37:08 -0700270 (bool)(fieldId & FIELD_COUNT_REPEATED), mDepth, mObjectId, sizePos);
271 return mExpectedObjectToken;
272}
273
274void
Yi Jin5ee07872018-03-05 18:18:27 -0800275ProtoOutputStream::end(uint64_t token)
Yi Jin974a9c22017-10-02 18:37:08 -0700276{
277 if (token != mExpectedObjectToken) {
Yi Jin00a75442018-03-30 11:01:58 -0700278 ALOGE("Unexpected token: 0x%" PRIx64 ", should be 0x%" PRIx64, token, mExpectedObjectToken);
Yi Jin18678bd2018-04-27 11:51:13 -0700279 mDepth = UINT32_C(-1); // make depth invalid
Yi Jin974a9c22017-10-02 18:37:08 -0700280 return;
281 }
282
Yi Jin00a75442018-03-30 11:01:58 -0700283 uint32_t depth = getDepthFromToken(token);
Yi Jin974a9c22017-10-02 18:37:08 -0700284 if (depth != (mDepth & 0x01ff)) {
Yi Jin00a75442018-03-30 11:01:58 -0700285 ALOGE("Unexpected depth: %" PRIu32 ", should be %" PRIu32, depth, mDepth);
Yi Jin18678bd2018-04-27 11:51:13 -0700286 mDepth = UINT32_C(-1); // make depth invalid
Yi Jin974a9c22017-10-02 18:37:08 -0700287 return;
288 }
289 mDepth--;
290
Yi Jin00a75442018-03-30 11:01:58 -0700291 uint32_t sizePos = getSizePosFromToken(token);
Yi Jin974a9c22017-10-02 18:37:08 -0700292 // number of bytes written in this start-end session.
Joe Onorato99598ee2019-02-11 15:55:13 +0000293 int childRawSize = mBuffer->wp()->pos() - sizePos - 8;
Yi Jin974a9c22017-10-02 18:37:08 -0700294
295 // retrieve the old token from stack.
Joe Onorato99598ee2019-02-11 15:55:13 +0000296 mBuffer->ep()->rewind()->move(sizePos);
297 mExpectedObjectToken = mBuffer->readRawFixed64();
Yi Jin974a9c22017-10-02 18:37:08 -0700298
299 // If raw size is larger than 0, write the negative value here to indicate a compact is needed.
300 if (childRawSize > 0) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000301 mBuffer->editRawFixed32(sizePos, -childRawSize);
302 mBuffer->editRawFixed32(sizePos+4, -1);
Yi Jin974a9c22017-10-02 18:37:08 -0700303 } else {
304 // reset wp which erase the header tag of the message when its size is 0.
Joe Onorato99598ee2019-02-11 15:55:13 +0000305 mBuffer->wp()->rewind()->move(sizePos - getTagSizeFromToken(token));
Yi Jin974a9c22017-10-02 18:37:08 -0700306 }
307}
308
Yi Jin0abdfb02017-11-16 15:32:27 -0800309size_t
310ProtoOutputStream::bytesWritten()
311{
Joe Onorato99598ee2019-02-11 15:55:13 +0000312 return mBuffer->size();
Yi Jin0abdfb02017-11-16 15:32:27 -0800313}
314
Yi Jin974a9c22017-10-02 18:37:08 -0700315bool
316ProtoOutputStream::compact() {
317 if (mCompact) return true;
318 if (mDepth != 0) {
Yi Jin18678bd2018-04-27 11:51:13 -0700319 ALOGE("Can't compact when depth(%" PRIu32 ") is not zero. Missing or extra calls to end.", mDepth);
Yi Jin974a9c22017-10-02 18:37:08 -0700320 return false;
321 }
322 // record the size of the original buffer.
Joe Onorato99598ee2019-02-11 15:55:13 +0000323 size_t rawBufferSize = mBuffer->size();
Yi Jin974a9c22017-10-02 18:37:08 -0700324 if (rawBufferSize == 0) return true; // nothing to do if the buffer is empty;
325
326 // reset edit pointer and recursively compute encoded size of messages.
Joe Onorato99598ee2019-02-11 15:55:13 +0000327 mBuffer->ep()->rewind();
Yi Jin974a9c22017-10-02 18:37:08 -0700328 if (editEncodedSize(rawBufferSize) == 0) {
329 ALOGE("Failed to editEncodedSize.");
330 return false;
331 }
332
333 // reset both edit pointer and write pointer, and compact recursively.
Joe Onorato99598ee2019-02-11 15:55:13 +0000334 mBuffer->ep()->rewind();
335 mBuffer->wp()->rewind();
Yi Jin974a9c22017-10-02 18:37:08 -0700336 if (!compactSize(rawBufferSize)) {
337 ALOGE("Failed to compactSize.");
338 return false;
339 }
340 // copy the reset to the buffer.
341 if (mCopyBegin < rawBufferSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000342 mBuffer->copy(mCopyBegin, rawBufferSize - mCopyBegin);
Yi Jin974a9c22017-10-02 18:37:08 -0700343 }
344
345 // mark true means it is not legal to write to this ProtoOutputStream anymore
346 mCompact = true;
347 return true;
348}
349
350/**
351 * First compaction pass. Iterate through the data, and fill in the
352 * nested object sizes so the next pass can compact them.
353 */
354size_t
355ProtoOutputStream::editEncodedSize(size_t rawSize)
356{
Joe Onorato99598ee2019-02-11 15:55:13 +0000357 size_t objectStart = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700358 size_t objectEnd = objectStart + rawSize;
359 size_t encodedSize = 0;
360 int childRawSize, childEncodedSize;
361 size_t childEncodedSizePos;
362
Joe Onorato99598ee2019-02-11 15:55:13 +0000363 while (mBuffer->ep()->pos() < objectEnd) {
364 uint32_t tag = (uint32_t)mBuffer->readRawVarint();
Yi Jin974a9c22017-10-02 18:37:08 -0700365 encodedSize += get_varint_size(tag);
366 switch (read_wire_type(tag)) {
367 case WIRE_TYPE_VARINT:
368 do {
369 encodedSize++;
Joe Onorato99598ee2019-02-11 15:55:13 +0000370 } while ((mBuffer->readRawByte() & 0x80) != 0);
Yi Jin974a9c22017-10-02 18:37:08 -0700371 break;
372 case WIRE_TYPE_FIXED64:
373 encodedSize += 8;
Joe Onorato99598ee2019-02-11 15:55:13 +0000374 mBuffer->ep()->move(8);
Yi Jin974a9c22017-10-02 18:37:08 -0700375 break;
376 case WIRE_TYPE_LENGTH_DELIMITED:
Joe Onorato99598ee2019-02-11 15:55:13 +0000377 childRawSize = (int)mBuffer->readRawFixed32();
378 childEncodedSizePos = mBuffer->ep()->pos();
379 childEncodedSize = (int)mBuffer->readRawFixed32();
Yi Jin974a9c22017-10-02 18:37:08 -0700380 if (childRawSize >= 0 && childRawSize == childEncodedSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000381 mBuffer->ep()->move(childRawSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700382 } else if (childRawSize < 0 && childEncodedSize == -1){
383 childEncodedSize = editEncodedSize(-childRawSize);
Joe Onorato99598ee2019-02-11 15:55:13 +0000384 mBuffer->editRawFixed32(childEncodedSizePos, childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700385 } else {
386 ALOGE("Bad raw or encoded values: raw=%d, encoded=%d at %zu",
387 childRawSize, childEncodedSize, childEncodedSizePos);
388 return 0;
389 }
390 encodedSize += get_varint_size(childEncodedSize) + childEncodedSize;
391 break;
392 case WIRE_TYPE_FIXED32:
393 encodedSize += 4;
Joe Onorato99598ee2019-02-11 15:55:13 +0000394 mBuffer->ep()->move(4);
Yi Jin974a9c22017-10-02 18:37:08 -0700395 break;
396 default:
397 ALOGE("Unexpected wire type %d in editEncodedSize at [%zu, %zu]",
398 read_wire_type(tag), objectStart, objectEnd);
399 return 0;
400 }
401 }
402 return encodedSize;
403}
404
405/**
406 * Second compaction pass. Iterate through the data, and copy the data
407 * forward in the buffer, converting the pairs of uint32s into a single
408 * unsigned varint of the size.
409 */
410bool
411ProtoOutputStream::compactSize(size_t rawSize)
412{
Joe Onorato99598ee2019-02-11 15:55:13 +0000413 size_t objectStart = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700414 size_t objectEnd = objectStart + rawSize;
415 int childRawSize, childEncodedSize;
416
Joe Onorato99598ee2019-02-11 15:55:13 +0000417 while (mBuffer->ep()->pos() < objectEnd) {
418 uint32_t tag = (uint32_t)mBuffer->readRawVarint();
Yi Jin974a9c22017-10-02 18:37:08 -0700419 switch (read_wire_type(tag)) {
420 case WIRE_TYPE_VARINT:
Joe Onorato99598ee2019-02-11 15:55:13 +0000421 while ((mBuffer->readRawByte() & 0x80) != 0) {}
Yi Jin974a9c22017-10-02 18:37:08 -0700422 break;
423 case WIRE_TYPE_FIXED64:
Joe Onorato99598ee2019-02-11 15:55:13 +0000424 mBuffer->ep()->move(8);
Yi Jin974a9c22017-10-02 18:37:08 -0700425 break;
426 case WIRE_TYPE_LENGTH_DELIMITED:
Joe Onorato99598ee2019-02-11 15:55:13 +0000427 mBuffer->copy(mCopyBegin, mBuffer->ep()->pos() - mCopyBegin);
Yi Jin974a9c22017-10-02 18:37:08 -0700428
Joe Onorato99598ee2019-02-11 15:55:13 +0000429 childRawSize = (int)mBuffer->readRawFixed32();
430 childEncodedSize = (int)mBuffer->readRawFixed32();
431 mCopyBegin = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700432
433 // write encoded size to buffer.
Joe Onorato99598ee2019-02-11 15:55:13 +0000434 mBuffer->writeRawVarint32(childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700435 if (childRawSize >= 0 && childRawSize == childEncodedSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000436 mBuffer->ep()->move(childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700437 } else if (childRawSize < 0){
438 if (!compactSize(-childRawSize)) return false;
439 } else {
440 ALOGE("Bad raw or encoded values: raw=%d, encoded=%d",
441 childRawSize, childEncodedSize);
442 return false;
443 }
444 break;
445 case WIRE_TYPE_FIXED32:
Joe Onorato99598ee2019-02-11 15:55:13 +0000446 mBuffer->ep()->move(4);
Yi Jin974a9c22017-10-02 18:37:08 -0700447 break;
448 default:
449 ALOGE("Unexpected wire type %d in compactSize at [%zu, %zu]",
450 read_wire_type(tag), objectStart, objectEnd);
451 return false;
452 }
453 }
454 return true;
455}
456
Yi Jin42711a02017-10-11 18:20:24 -0700457size_t
458ProtoOutputStream::size()
459{
Yi Jin00a75442018-03-30 11:01:58 -0700460 if (!compact()) {
461 ALOGE("compact failed, the ProtoOutputStream data is corrupted!");
Yi Jin18678bd2018-04-27 11:51:13 -0700462 return 0;
Yi Jin00a75442018-03-30 11:01:58 -0700463 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000464 return mBuffer->size();
Yi Jin42711a02017-10-11 18:20:24 -0700465}
466
Yi Jin974a9c22017-10-02 18:37:08 -0700467bool
Yi Jin42711a02017-10-11 18:20:24 -0700468ProtoOutputStream::flush(int fd)
Yi Jin974a9c22017-10-02 18:37:08 -0700469{
Yi Jin42711a02017-10-11 18:20:24 -0700470 if (fd < 0) return false;
Yi Jin974a9c22017-10-02 18:37:08 -0700471 if (!compact()) return false;
472
Joe Onorato99598ee2019-02-11 15:55:13 +0000473 sp<ProtoReader> reader = mBuffer->read();
474 while (reader->readBuffer() != NULL) {
475 if (!android::base::WriteFully(fd, reader->readBuffer(), reader->currentToRead())) {
476 return false;
477 }
478 reader->move(reader->currentToRead());
Yi Jin974a9c22017-10-02 18:37:08 -0700479 }
480 return true;
481}
482
Tej Singhf53d4452019-05-09 18:17:59 -0700483bool
484ProtoOutputStream::serializeToString(std::string* out)
485{
486 if (out == nullptr) return false;
487 if (!compact()) return false;
488
Tej Singhf53d4452019-05-09 18:17:59 -0700489 sp<ProtoReader> reader = mBuffer->read();
490 out->reserve(reader->size());
491 while (reader->hasNext()) {
492 out->append(static_cast<const char*>(static_cast<const void*>(reader->readBuffer())),
493 reader->currentToRead());
494 reader->move(reader->currentToRead());
495 }
496 return true;
497}
498
Joe Onoratodcd64522019-05-19 17:35:08 -0700499bool
500ProtoOutputStream::serializeToVector(std::vector<uint8_t>* out)
501{
502 if (out == nullptr) return false;
503 if (!compact()) return false;
504
505 sp<ProtoReader> reader = mBuffer->read();
506 out->reserve(reader->size());
507 while (reader->hasNext()) {
508 const uint8_t* buf = reader->readBuffer();
509 size_t size = reader->currentToRead();
510 out->insert(out->end(), buf, buf + size);
511 reader->move(size);
512 }
513 return true;
514}
515
Joe Onorato99598ee2019-02-11 15:55:13 +0000516sp<ProtoReader>
Yi Jin42711a02017-10-11 18:20:24 -0700517ProtoOutputStream::data()
518{
Yi Jin00a75442018-03-30 11:01:58 -0700519 if (!compact()) {
520 ALOGE("compact failed, the ProtoOutputStream data is corrupted!");
Joe Onorato99598ee2019-02-11 15:55:13 +0000521 mBuffer->clear();
Yi Jin00a75442018-03-30 11:01:58 -0700522 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000523 return mBuffer->read();
Yi Jin42711a02017-10-11 18:20:24 -0700524}
525
526void
527ProtoOutputStream::writeRawVarint(uint64_t varint)
528{
Joe Onorato99598ee2019-02-11 15:55:13 +0000529 mBuffer->writeRawVarint64(varint);
Yi Jin42711a02017-10-11 18:20:24 -0700530}
531
532void
533ProtoOutputStream::writeLengthDelimitedHeader(uint32_t id, size_t size)
534{
Joe Onorato99598ee2019-02-11 15:55:13 +0000535 mBuffer->writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
Yi Jin42711a02017-10-11 18:20:24 -0700536 // reserves 64 bits for length delimited fields, if first field is negative, compact it.
Joe Onorato99598ee2019-02-11 15:55:13 +0000537 mBuffer->writeRawFixed32(size);
538 mBuffer->writeRawFixed32(size);
Yi Jin42711a02017-10-11 18:20:24 -0700539}
540
541void
542ProtoOutputStream::writeRawByte(uint8_t byte)
543{
Joe Onorato99598ee2019-02-11 15:55:13 +0000544 mBuffer->writeRawByte(byte);
Yi Jin42711a02017-10-11 18:20:24 -0700545}
546
Yi Jin974a9c22017-10-02 18:37:08 -0700547
548// =========================================================================
549// Private functions
550
551/**
552 * bit_cast
553 */
554template <class From, class To>
555inline To bit_cast(From const &from) {
556 To to;
557 memcpy(&to, &from, sizeof(to));
558 return to;
559}
560
561inline void
562ProtoOutputStream::writeDoubleImpl(uint32_t id, double val)
563{
Joe Onorato99598ee2019-02-11 15:55:13 +0000564 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
565 mBuffer->writeRawFixed64(bit_cast<double, uint64_t>(val));
Yi Jin974a9c22017-10-02 18:37:08 -0700566}
567
568inline void
569ProtoOutputStream::writeFloatImpl(uint32_t id, float val)
570{
Joe Onorato99598ee2019-02-11 15:55:13 +0000571 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
572 mBuffer->writeRawFixed32(bit_cast<float, uint32_t>(val));
Yi Jin974a9c22017-10-02 18:37:08 -0700573}
574
575inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700576ProtoOutputStream::writeInt64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700577{
Joe Onorato99598ee2019-02-11 15:55:13 +0000578 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
579 mBuffer->writeRawVarint64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700580}
581
582inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700583ProtoOutputStream::writeInt32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700584{
Joe Onorato99598ee2019-02-11 15:55:13 +0000585 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
586 mBuffer->writeRawVarint32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700587}
588
589inline void
590ProtoOutputStream::writeUint64Impl(uint32_t id, uint64_t val)
591{
Joe Onorato99598ee2019-02-11 15:55:13 +0000592 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
593 mBuffer->writeRawVarint64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700594}
595
596inline void
597ProtoOutputStream::writeUint32Impl(uint32_t id, uint32_t val)
598{
Joe Onorato99598ee2019-02-11 15:55:13 +0000599 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
600 mBuffer->writeRawVarint32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700601}
602
603inline void
604ProtoOutputStream::writeFixed64Impl(uint32_t id, uint64_t val)
605{
Joe Onorato99598ee2019-02-11 15:55:13 +0000606 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
607 mBuffer->writeRawFixed64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700608}
609
610inline void
611ProtoOutputStream::writeFixed32Impl(uint32_t id, uint32_t val)
612{
Joe Onorato99598ee2019-02-11 15:55:13 +0000613 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
614 mBuffer->writeRawFixed32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700615}
616
617inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700618ProtoOutputStream::writeSFixed64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700619{
Joe Onorato99598ee2019-02-11 15:55:13 +0000620 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
621 mBuffer->writeRawFixed64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700622}
623
624inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700625ProtoOutputStream::writeSFixed32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700626{
Joe Onorato99598ee2019-02-11 15:55:13 +0000627 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
628 mBuffer->writeRawFixed32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700629}
630
631inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700632ProtoOutputStream::writeZigzagInt64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700633{
Joe Onorato99598ee2019-02-11 15:55:13 +0000634 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
635 mBuffer->writeRawVarint64((val << 1) ^ (val >> 63));
Yi Jin974a9c22017-10-02 18:37:08 -0700636}
637
638inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700639ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700640{
Joe Onorato99598ee2019-02-11 15:55:13 +0000641 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
642 mBuffer->writeRawVarint32((val << 1) ^ (val >> 31));
Yi Jin974a9c22017-10-02 18:37:08 -0700643}
644
645inline void
646ProtoOutputStream::writeEnumImpl(uint32_t id, int val)
647{
Joe Onorato99598ee2019-02-11 15:55:13 +0000648 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
649 mBuffer->writeRawVarint32((uint32_t) val);
Yi Jin974a9c22017-10-02 18:37:08 -0700650}
651
652inline void
653ProtoOutputStream::writeBoolImpl(uint32_t id, bool val)
654{
Joe Onorato99598ee2019-02-11 15:55:13 +0000655 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
656 mBuffer->writeRawVarint32(val ? 1 : 0);
Yi Jin974a9c22017-10-02 18:37:08 -0700657}
658
659inline void
660ProtoOutputStream::writeUtf8StringImpl(uint32_t id, const char* val, size_t size)
661{
Yi Jin04625ad2017-10-17 18:29:33 -0700662 if (val == NULL) return;
Yi Jin42711a02017-10-11 18:20:24 -0700663 writeLengthDelimitedHeader(id, size);
Yi Jin974a9c22017-10-02 18:37:08 -0700664 for (size_t i=0; i<size; i++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000665 mBuffer->writeRawByte((uint8_t)val[i]);
Yi Jin974a9c22017-10-02 18:37:08 -0700666 }
667}
668
Yi Jin8ad19382017-10-30 16:07:20 -0700669inline void
670ProtoOutputStream::writeMessageBytesImpl(uint32_t id, const char* val, size_t size)
671{
672 if (val == NULL) return;
673 writeLengthDelimitedHeader(id, size);
674 for (size_t i=0; i<size; i++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000675 mBuffer->writeRawByte(val[i]);
Yi Jin8ad19382017-10-30 16:07:20 -0700676 }
677}
678
Yi Jin974a9c22017-10-02 18:37:08 -0700679} // util
680} // android
681