blob: 6cfa357b580bbb1450720728c20f20bfabb2628c [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
119ProtoOutputStream::write(uint64_t fieldId, long long val)
120{
Yi Jinfd2a4c72018-04-26 11:49:08 -0700121 return internalWrite(fieldId, val, "long long");
Yi Jin974a9c22017-10-02 18:37:08 -0700122}
123
124bool
125ProtoOutputStream::write(uint64_t fieldId, bool val)
126{
127 if (mCompact) return false;
128 const uint32_t id = (uint32_t)fieldId;
129 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700130 case FIELD_TYPE_BOOL:
Yi Jin974a9c22017-10-02 18:37:08 -0700131 writeBoolImpl(id, val);
132 return true;
133 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700134 ALOGW("Field type %" PRIu64 " is not supported when writing bool val.",
135 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700136 return false;
137 }
138}
139
140bool
Yi Jin6cacbcb2018-03-30 14:04:52 -0700141ProtoOutputStream::write(uint64_t fieldId, std::string val)
Yi Jin974a9c22017-10-02 18:37:08 -0700142{
143 if (mCompact) return false;
144 const uint32_t id = (uint32_t)fieldId;
145 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700146 case FIELD_TYPE_STRING:
Yi Jin974a9c22017-10-02 18:37:08 -0700147 writeUtf8StringImpl(id, val.c_str(), val.size());
148 return true;
149 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700150 ALOGW("Field type %" PRIu64 " is not supported when writing string val.",
151 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700152 return false;
153 }
154}
155
156bool
Yi Jine0833302017-10-23 15:42:44 -0700157ProtoOutputStream::write(uint64_t fieldId, const char* val, size_t size)
Yi Jin974a9c22017-10-02 18:37:08 -0700158{
159 if (mCompact) return false;
160 const uint32_t id = (uint32_t)fieldId;
Yi Jin974a9c22017-10-02 18:37:08 -0700161 switch (fieldId & FIELD_TYPE_MASK) {
Yi Jin04625ad2017-10-17 18:29:33 -0700162 case FIELD_TYPE_STRING:
163 case FIELD_TYPE_BYTES:
Yi Jin974a9c22017-10-02 18:37:08 -0700164 writeUtf8StringImpl(id, val, size);
165 return true;
Yi Jin04625ad2017-10-17 18:29:33 -0700166 case FIELD_TYPE_MESSAGE:
Yi Jin8ad19382017-10-30 16:07:20 -0700167 // can directly write valid format of message bytes into ProtoOutputStream without calling start/end
168 writeMessageBytesImpl(id, val, size);
169 return true;
Yi Jin974a9c22017-10-02 18:37:08 -0700170 default:
Yi Jinfd2a4c72018-04-26 11:49:08 -0700171 ALOGW("Field type %" PRIu64 " is not supported when writing char[] val.",
172 (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
Yi Jin974a9c22017-10-02 18:37:08 -0700173 return false;
174 }
175}
176
177/**
178 * Make a token.
179 * Bits 61-63 - tag size (So we can go backwards later if the object had not data)
180 * - 3 bits, max value 7, max value needed 5
181 * Bit 60 - true if the object is repeated
182 * Bits 59-51 - depth (For error checking)
Yi Jin00a75442018-03-30 11:01:58 -0700183 * - 9 bits, max value 511, when checking, value is masked (if we really
184 * are more than 511 levels deep)
Yi Jin974a9c22017-10-02 18:37:08 -0700185 * Bits 32-50 - objectId (For error checking)
Yi Jin00a75442018-03-30 11:01:58 -0700186 * - 19 bits, max value 524,287. that's a lot of objects. IDs will wrap
Yi Jin974a9c22017-10-02 18:37:08 -0700187 * because of the overflow, and only the tokens are compared.
188 * Bits 0-31 - offset of the first size field in the buffer.
189 */
Yi Jin00a75442018-03-30 11:01:58 -0700190static uint64_t
191makeToken(uint32_t tagSize, bool repeated, uint32_t depth, uint32_t objectId, size_t sizePos) {
192 return ((UINT64_C(0x07) & (uint64_t)tagSize) << 61)
193 | (repeated ? (UINT64_C(1) << 60) : 0)
194 | (UINT64_C(0x01ff) & (uint64_t)depth) << 51
195 | (UINT64_C(0x07ffff) & (uint64_t)objectId) << 32
196 | (UINT64_C(0x0ffffffff) & (uint64_t)sizePos);
Yi Jin974a9c22017-10-02 18:37:08 -0700197}
198
199/**
200 * Get the encoded tag size from the token.
201 */
Yi Jin00a75442018-03-30 11:01:58 -0700202static uint32_t getTagSizeFromToken(uint64_t token) {
203 return 0x7 & (token >> 61);
Yi Jin974a9c22017-10-02 18:37:08 -0700204}
205
206/**
207 * Get the nesting depth of startObject calls from the token.
208 */
Yi Jin00a75442018-03-30 11:01:58 -0700209static uint32_t getDepthFromToken(uint64_t token) {
210 return 0x01ff & (token >> 51);
Yi Jin974a9c22017-10-02 18:37:08 -0700211}
212
213/**
214 * Get the location of the childRawSize (the first 32 bit size field) in this object.
215 */
Yi Jin00a75442018-03-30 11:01:58 -0700216static uint32_t getSizePosFromToken(uint64_t token) {
217 return (uint32_t)token;
Yi Jin974a9c22017-10-02 18:37:08 -0700218}
219
Yi Jin5ee07872018-03-05 18:18:27 -0800220uint64_t
Yi Jin974a9c22017-10-02 18:37:08 -0700221ProtoOutputStream::start(uint64_t fieldId)
222{
Yi Jin04625ad2017-10-17 18:29:33 -0700223 if ((fieldId & FIELD_TYPE_MASK) != FIELD_TYPE_MESSAGE) {
Yi Jin00a75442018-03-30 11:01:58 -0700224 ALOGE("Can't call start for non-message type field: 0x%" PRIx64, fieldId);
Yi Jin974a9c22017-10-02 18:37:08 -0700225 return 0;
226 }
227
228 uint32_t id = (uint32_t)fieldId;
Joe Onorato99598ee2019-02-11 15:55:13 +0000229 size_t prevPos = mBuffer->wp()->pos();
230 mBuffer->writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
231 size_t sizePos = mBuffer->wp()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700232
233 mDepth++;
234 mObjectId++;
Joe Onorato99598ee2019-02-11 15:55:13 +0000235 mBuffer->writeRawFixed64(mExpectedObjectToken); // push previous token into stack.
Yi Jin974a9c22017-10-02 18:37:08 -0700236
Yi Jin295d9b12018-02-02 14:33:20 -0800237 mExpectedObjectToken = makeToken(sizePos - prevPos,
Yi Jin974a9c22017-10-02 18:37:08 -0700238 (bool)(fieldId & FIELD_COUNT_REPEATED), mDepth, mObjectId, sizePos);
239 return mExpectedObjectToken;
240}
241
242void
Yi Jin5ee07872018-03-05 18:18:27 -0800243ProtoOutputStream::end(uint64_t token)
Yi Jin974a9c22017-10-02 18:37:08 -0700244{
245 if (token != mExpectedObjectToken) {
Yi Jin00a75442018-03-30 11:01:58 -0700246 ALOGE("Unexpected token: 0x%" PRIx64 ", should be 0x%" PRIx64, token, mExpectedObjectToken);
Yi Jin18678bd2018-04-27 11:51:13 -0700247 mDepth = UINT32_C(-1); // make depth invalid
Yi Jin974a9c22017-10-02 18:37:08 -0700248 return;
249 }
250
Yi Jin00a75442018-03-30 11:01:58 -0700251 uint32_t depth = getDepthFromToken(token);
Yi Jin974a9c22017-10-02 18:37:08 -0700252 if (depth != (mDepth & 0x01ff)) {
Yi Jin00a75442018-03-30 11:01:58 -0700253 ALOGE("Unexpected depth: %" PRIu32 ", should be %" PRIu32, depth, mDepth);
Yi Jin18678bd2018-04-27 11:51:13 -0700254 mDepth = UINT32_C(-1); // make depth invalid
Yi Jin974a9c22017-10-02 18:37:08 -0700255 return;
256 }
257 mDepth--;
258
Yi Jin00a75442018-03-30 11:01:58 -0700259 uint32_t sizePos = getSizePosFromToken(token);
Yi Jin974a9c22017-10-02 18:37:08 -0700260 // number of bytes written in this start-end session.
Joe Onorato99598ee2019-02-11 15:55:13 +0000261 int childRawSize = mBuffer->wp()->pos() - sizePos - 8;
Yi Jin974a9c22017-10-02 18:37:08 -0700262
263 // retrieve the old token from stack.
Joe Onorato99598ee2019-02-11 15:55:13 +0000264 mBuffer->ep()->rewind()->move(sizePos);
265 mExpectedObjectToken = mBuffer->readRawFixed64();
Yi Jin974a9c22017-10-02 18:37:08 -0700266
267 // If raw size is larger than 0, write the negative value here to indicate a compact is needed.
268 if (childRawSize > 0) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000269 mBuffer->editRawFixed32(sizePos, -childRawSize);
270 mBuffer->editRawFixed32(sizePos+4, -1);
Yi Jin974a9c22017-10-02 18:37:08 -0700271 } else {
272 // reset wp which erase the header tag of the message when its size is 0.
Joe Onorato99598ee2019-02-11 15:55:13 +0000273 mBuffer->wp()->rewind()->move(sizePos - getTagSizeFromToken(token));
Yi Jin974a9c22017-10-02 18:37:08 -0700274 }
275}
276
Yi Jin0abdfb02017-11-16 15:32:27 -0800277size_t
278ProtoOutputStream::bytesWritten()
279{
Joe Onorato99598ee2019-02-11 15:55:13 +0000280 return mBuffer->size();
Yi Jin0abdfb02017-11-16 15:32:27 -0800281}
282
Yi Jin974a9c22017-10-02 18:37:08 -0700283bool
284ProtoOutputStream::compact() {
285 if (mCompact) return true;
286 if (mDepth != 0) {
Yi Jin18678bd2018-04-27 11:51:13 -0700287 ALOGE("Can't compact when depth(%" PRIu32 ") is not zero. Missing or extra calls to end.", mDepth);
Yi Jin974a9c22017-10-02 18:37:08 -0700288 return false;
289 }
290 // record the size of the original buffer.
Joe Onorato99598ee2019-02-11 15:55:13 +0000291 size_t rawBufferSize = mBuffer->size();
Yi Jin974a9c22017-10-02 18:37:08 -0700292 if (rawBufferSize == 0) return true; // nothing to do if the buffer is empty;
293
294 // reset edit pointer and recursively compute encoded size of messages.
Joe Onorato99598ee2019-02-11 15:55:13 +0000295 mBuffer->ep()->rewind();
Yi Jin974a9c22017-10-02 18:37:08 -0700296 if (editEncodedSize(rawBufferSize) == 0) {
297 ALOGE("Failed to editEncodedSize.");
298 return false;
299 }
300
301 // reset both edit pointer and write pointer, and compact recursively.
Joe Onorato99598ee2019-02-11 15:55:13 +0000302 mBuffer->ep()->rewind();
303 mBuffer->wp()->rewind();
Yi Jin974a9c22017-10-02 18:37:08 -0700304 if (!compactSize(rawBufferSize)) {
305 ALOGE("Failed to compactSize.");
306 return false;
307 }
308 // copy the reset to the buffer.
309 if (mCopyBegin < rawBufferSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000310 mBuffer->copy(mCopyBegin, rawBufferSize - mCopyBegin);
Yi Jin974a9c22017-10-02 18:37:08 -0700311 }
312
313 // mark true means it is not legal to write to this ProtoOutputStream anymore
314 mCompact = true;
315 return true;
316}
317
318/**
319 * First compaction pass. Iterate through the data, and fill in the
320 * nested object sizes so the next pass can compact them.
321 */
322size_t
323ProtoOutputStream::editEncodedSize(size_t rawSize)
324{
Joe Onorato99598ee2019-02-11 15:55:13 +0000325 size_t objectStart = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700326 size_t objectEnd = objectStart + rawSize;
327 size_t encodedSize = 0;
328 int childRawSize, childEncodedSize;
329 size_t childEncodedSizePos;
330
Joe Onorato99598ee2019-02-11 15:55:13 +0000331 while (mBuffer->ep()->pos() < objectEnd) {
332 uint32_t tag = (uint32_t)mBuffer->readRawVarint();
Yi Jin974a9c22017-10-02 18:37:08 -0700333 encodedSize += get_varint_size(tag);
334 switch (read_wire_type(tag)) {
335 case WIRE_TYPE_VARINT:
336 do {
337 encodedSize++;
Joe Onorato99598ee2019-02-11 15:55:13 +0000338 } while ((mBuffer->readRawByte() & 0x80) != 0);
Yi Jin974a9c22017-10-02 18:37:08 -0700339 break;
340 case WIRE_TYPE_FIXED64:
341 encodedSize += 8;
Joe Onorato99598ee2019-02-11 15:55:13 +0000342 mBuffer->ep()->move(8);
Yi Jin974a9c22017-10-02 18:37:08 -0700343 break;
344 case WIRE_TYPE_LENGTH_DELIMITED:
Joe Onorato99598ee2019-02-11 15:55:13 +0000345 childRawSize = (int)mBuffer->readRawFixed32();
346 childEncodedSizePos = mBuffer->ep()->pos();
347 childEncodedSize = (int)mBuffer->readRawFixed32();
Yi Jin974a9c22017-10-02 18:37:08 -0700348 if (childRawSize >= 0 && childRawSize == childEncodedSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000349 mBuffer->ep()->move(childRawSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700350 } else if (childRawSize < 0 && childEncodedSize == -1){
351 childEncodedSize = editEncodedSize(-childRawSize);
Joe Onorato99598ee2019-02-11 15:55:13 +0000352 mBuffer->editRawFixed32(childEncodedSizePos, childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700353 } else {
354 ALOGE("Bad raw or encoded values: raw=%d, encoded=%d at %zu",
355 childRawSize, childEncodedSize, childEncodedSizePos);
356 return 0;
357 }
358 encodedSize += get_varint_size(childEncodedSize) + childEncodedSize;
359 break;
360 case WIRE_TYPE_FIXED32:
361 encodedSize += 4;
Joe Onorato99598ee2019-02-11 15:55:13 +0000362 mBuffer->ep()->move(4);
Yi Jin974a9c22017-10-02 18:37:08 -0700363 break;
364 default:
365 ALOGE("Unexpected wire type %d in editEncodedSize at [%zu, %zu]",
366 read_wire_type(tag), objectStart, objectEnd);
367 return 0;
368 }
369 }
370 return encodedSize;
371}
372
373/**
374 * Second compaction pass. Iterate through the data, and copy the data
375 * forward in the buffer, converting the pairs of uint32s into a single
376 * unsigned varint of the size.
377 */
378bool
379ProtoOutputStream::compactSize(size_t rawSize)
380{
Joe Onorato99598ee2019-02-11 15:55:13 +0000381 size_t objectStart = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700382 size_t objectEnd = objectStart + rawSize;
383 int childRawSize, childEncodedSize;
384
Joe Onorato99598ee2019-02-11 15:55:13 +0000385 while (mBuffer->ep()->pos() < objectEnd) {
386 uint32_t tag = (uint32_t)mBuffer->readRawVarint();
Yi Jin974a9c22017-10-02 18:37:08 -0700387 switch (read_wire_type(tag)) {
388 case WIRE_TYPE_VARINT:
Joe Onorato99598ee2019-02-11 15:55:13 +0000389 while ((mBuffer->readRawByte() & 0x80) != 0) {}
Yi Jin974a9c22017-10-02 18:37:08 -0700390 break;
391 case WIRE_TYPE_FIXED64:
Joe Onorato99598ee2019-02-11 15:55:13 +0000392 mBuffer->ep()->move(8);
Yi Jin974a9c22017-10-02 18:37:08 -0700393 break;
394 case WIRE_TYPE_LENGTH_DELIMITED:
Joe Onorato99598ee2019-02-11 15:55:13 +0000395 mBuffer->copy(mCopyBegin, mBuffer->ep()->pos() - mCopyBegin);
Yi Jin974a9c22017-10-02 18:37:08 -0700396
Joe Onorato99598ee2019-02-11 15:55:13 +0000397 childRawSize = (int)mBuffer->readRawFixed32();
398 childEncodedSize = (int)mBuffer->readRawFixed32();
399 mCopyBegin = mBuffer->ep()->pos();
Yi Jin974a9c22017-10-02 18:37:08 -0700400
401 // write encoded size to buffer.
Joe Onorato99598ee2019-02-11 15:55:13 +0000402 mBuffer->writeRawVarint32(childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700403 if (childRawSize >= 0 && childRawSize == childEncodedSize) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000404 mBuffer->ep()->move(childEncodedSize);
Yi Jin974a9c22017-10-02 18:37:08 -0700405 } else if (childRawSize < 0){
406 if (!compactSize(-childRawSize)) return false;
407 } else {
408 ALOGE("Bad raw or encoded values: raw=%d, encoded=%d",
409 childRawSize, childEncodedSize);
410 return false;
411 }
412 break;
413 case WIRE_TYPE_FIXED32:
Joe Onorato99598ee2019-02-11 15:55:13 +0000414 mBuffer->ep()->move(4);
Yi Jin974a9c22017-10-02 18:37:08 -0700415 break;
416 default:
417 ALOGE("Unexpected wire type %d in compactSize at [%zu, %zu]",
418 read_wire_type(tag), objectStart, objectEnd);
419 return false;
420 }
421 }
422 return true;
423}
424
Yi Jin42711a02017-10-11 18:20:24 -0700425size_t
426ProtoOutputStream::size()
427{
Yi Jin00a75442018-03-30 11:01:58 -0700428 if (!compact()) {
429 ALOGE("compact failed, the ProtoOutputStream data is corrupted!");
Yi Jin18678bd2018-04-27 11:51:13 -0700430 return 0;
Yi Jin00a75442018-03-30 11:01:58 -0700431 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000432 return mBuffer->size();
Yi Jin42711a02017-10-11 18:20:24 -0700433}
434
Yi Jin974a9c22017-10-02 18:37:08 -0700435bool
Yi Jin42711a02017-10-11 18:20:24 -0700436ProtoOutputStream::flush(int fd)
Yi Jin974a9c22017-10-02 18:37:08 -0700437{
Yi Jin42711a02017-10-11 18:20:24 -0700438 if (fd < 0) return false;
Yi Jin974a9c22017-10-02 18:37:08 -0700439 if (!compact()) return false;
440
Joe Onorato99598ee2019-02-11 15:55:13 +0000441 sp<ProtoReader> reader = mBuffer->read();
442 while (reader->readBuffer() != NULL) {
443 if (!android::base::WriteFully(fd, reader->readBuffer(), reader->currentToRead())) {
444 return false;
445 }
446 reader->move(reader->currentToRead());
Yi Jin974a9c22017-10-02 18:37:08 -0700447 }
448 return true;
449}
450
Tej Singhf53d4452019-05-09 18:17:59 -0700451bool
452ProtoOutputStream::serializeToString(std::string* out)
453{
454 if (out == nullptr) return false;
455 if (!compact()) return false;
456
Tej Singhf53d4452019-05-09 18:17:59 -0700457 sp<ProtoReader> reader = mBuffer->read();
458 out->reserve(reader->size());
459 while (reader->hasNext()) {
460 out->append(static_cast<const char*>(static_cast<const void*>(reader->readBuffer())),
461 reader->currentToRead());
462 reader->move(reader->currentToRead());
463 }
464 return true;
465}
466
Joe Onoratodcd64522019-05-19 17:35:08 -0700467bool
468ProtoOutputStream::serializeToVector(std::vector<uint8_t>* out)
469{
470 if (out == nullptr) return false;
471 if (!compact()) return false;
472
473 sp<ProtoReader> reader = mBuffer->read();
474 out->reserve(reader->size());
475 while (reader->hasNext()) {
476 const uint8_t* buf = reader->readBuffer();
477 size_t size = reader->currentToRead();
478 out->insert(out->end(), buf, buf + size);
479 reader->move(size);
480 }
481 return true;
482}
483
Joe Onorato99598ee2019-02-11 15:55:13 +0000484sp<ProtoReader>
Yi Jin42711a02017-10-11 18:20:24 -0700485ProtoOutputStream::data()
486{
Yi Jin00a75442018-03-30 11:01:58 -0700487 if (!compact()) {
488 ALOGE("compact failed, the ProtoOutputStream data is corrupted!");
Joe Onorato99598ee2019-02-11 15:55:13 +0000489 mBuffer->clear();
Yi Jin00a75442018-03-30 11:01:58 -0700490 }
Joe Onorato99598ee2019-02-11 15:55:13 +0000491 return mBuffer->read();
Yi Jin42711a02017-10-11 18:20:24 -0700492}
493
494void
495ProtoOutputStream::writeRawVarint(uint64_t varint)
496{
Joe Onorato99598ee2019-02-11 15:55:13 +0000497 mBuffer->writeRawVarint64(varint);
Yi Jin42711a02017-10-11 18:20:24 -0700498}
499
500void
501ProtoOutputStream::writeLengthDelimitedHeader(uint32_t id, size_t size)
502{
Joe Onorato99598ee2019-02-11 15:55:13 +0000503 mBuffer->writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
Yi Jin42711a02017-10-11 18:20:24 -0700504 // reserves 64 bits for length delimited fields, if first field is negative, compact it.
Joe Onorato99598ee2019-02-11 15:55:13 +0000505 mBuffer->writeRawFixed32(size);
506 mBuffer->writeRawFixed32(size);
Yi Jin42711a02017-10-11 18:20:24 -0700507}
508
509void
510ProtoOutputStream::writeRawByte(uint8_t byte)
511{
Joe Onorato99598ee2019-02-11 15:55:13 +0000512 mBuffer->writeRawByte(byte);
Yi Jin42711a02017-10-11 18:20:24 -0700513}
514
Yi Jin974a9c22017-10-02 18:37:08 -0700515
516// =========================================================================
517// Private functions
518
519/**
520 * bit_cast
521 */
522template <class From, class To>
523inline To bit_cast(From const &from) {
524 To to;
525 memcpy(&to, &from, sizeof(to));
526 return to;
527}
528
529inline void
530ProtoOutputStream::writeDoubleImpl(uint32_t id, double val)
531{
Joe Onorato99598ee2019-02-11 15:55:13 +0000532 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
533 mBuffer->writeRawFixed64(bit_cast<double, uint64_t>(val));
Yi Jin974a9c22017-10-02 18:37:08 -0700534}
535
536inline void
537ProtoOutputStream::writeFloatImpl(uint32_t id, float val)
538{
Joe Onorato99598ee2019-02-11 15:55:13 +0000539 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
540 mBuffer->writeRawFixed32(bit_cast<float, uint32_t>(val));
Yi Jin974a9c22017-10-02 18:37:08 -0700541}
542
543inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700544ProtoOutputStream::writeInt64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700545{
Joe Onorato99598ee2019-02-11 15:55:13 +0000546 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
547 mBuffer->writeRawVarint64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700548}
549
550inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700551ProtoOutputStream::writeInt32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700552{
Joe Onorato99598ee2019-02-11 15:55:13 +0000553 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
554 mBuffer->writeRawVarint32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700555}
556
557inline void
558ProtoOutputStream::writeUint64Impl(uint32_t id, uint64_t val)
559{
Joe Onorato99598ee2019-02-11 15:55:13 +0000560 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
561 mBuffer->writeRawVarint64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700562}
563
564inline void
565ProtoOutputStream::writeUint32Impl(uint32_t id, uint32_t val)
566{
Joe Onorato99598ee2019-02-11 15:55:13 +0000567 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
568 mBuffer->writeRawVarint32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700569}
570
571inline void
572ProtoOutputStream::writeFixed64Impl(uint32_t id, uint64_t val)
573{
Joe Onorato99598ee2019-02-11 15:55:13 +0000574 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
575 mBuffer->writeRawFixed64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700576}
577
578inline void
579ProtoOutputStream::writeFixed32Impl(uint32_t id, uint32_t val)
580{
Joe Onorato99598ee2019-02-11 15:55:13 +0000581 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
582 mBuffer->writeRawFixed32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700583}
584
585inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700586ProtoOutputStream::writeSFixed64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700587{
Joe Onorato99598ee2019-02-11 15:55:13 +0000588 mBuffer->writeHeader(id, WIRE_TYPE_FIXED64);
589 mBuffer->writeRawFixed64(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700590}
591
592inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700593ProtoOutputStream::writeSFixed32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700594{
Joe Onorato99598ee2019-02-11 15:55:13 +0000595 mBuffer->writeHeader(id, WIRE_TYPE_FIXED32);
596 mBuffer->writeRawFixed32(val);
Yi Jin974a9c22017-10-02 18:37:08 -0700597}
598
599inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700600ProtoOutputStream::writeZigzagInt64Impl(uint32_t id, int64_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700601{
Joe Onorato99598ee2019-02-11 15:55:13 +0000602 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
603 mBuffer->writeRawVarint64((val << 1) ^ (val >> 63));
Yi Jin974a9c22017-10-02 18:37:08 -0700604}
605
606inline void
Yi Jinfd2a4c72018-04-26 11:49:08 -0700607ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int32_t val)
Yi Jin974a9c22017-10-02 18:37:08 -0700608{
Joe Onorato99598ee2019-02-11 15:55:13 +0000609 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
610 mBuffer->writeRawVarint32((val << 1) ^ (val >> 31));
Yi Jin974a9c22017-10-02 18:37:08 -0700611}
612
613inline void
614ProtoOutputStream::writeEnumImpl(uint32_t id, int val)
615{
Joe Onorato99598ee2019-02-11 15:55:13 +0000616 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
617 mBuffer->writeRawVarint32((uint32_t) val);
Yi Jin974a9c22017-10-02 18:37:08 -0700618}
619
620inline void
621ProtoOutputStream::writeBoolImpl(uint32_t id, bool val)
622{
Joe Onorato99598ee2019-02-11 15:55:13 +0000623 mBuffer->writeHeader(id, WIRE_TYPE_VARINT);
624 mBuffer->writeRawVarint32(val ? 1 : 0);
Yi Jin974a9c22017-10-02 18:37:08 -0700625}
626
627inline void
628ProtoOutputStream::writeUtf8StringImpl(uint32_t id, const char* val, size_t size)
629{
Yi Jin04625ad2017-10-17 18:29:33 -0700630 if (val == NULL) return;
Yi Jin42711a02017-10-11 18:20:24 -0700631 writeLengthDelimitedHeader(id, size);
Yi Jin974a9c22017-10-02 18:37:08 -0700632 for (size_t i=0; i<size; i++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000633 mBuffer->writeRawByte((uint8_t)val[i]);
Yi Jin974a9c22017-10-02 18:37:08 -0700634 }
635}
636
Yi Jin8ad19382017-10-30 16:07:20 -0700637inline void
638ProtoOutputStream::writeMessageBytesImpl(uint32_t id, const char* val, size_t size)
639{
640 if (val == NULL) return;
641 writeLengthDelimitedHeader(id, size);
642 for (size_t i=0; i<size; i++) {
Joe Onorato99598ee2019-02-11 15:55:13 +0000643 mBuffer->writeRawByte(val[i]);
Yi Jin8ad19382017-10-30 16:07:20 -0700644 }
645}
646
Yi Jin974a9c22017-10-02 18:37:08 -0700647} // util
648} // android
649