1974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin/*
2974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * Copyright (C) 2017 The Android Open Source Project
3974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin *
4974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * Licensed under the Apache License, Version 2.0 (the "License");
5974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * you may not use this file except in compliance with the License.
6974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * You may obtain a copy of the License at
7974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin *
8974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin *      http://www.apache.org/licenses/LICENSE-2.0
9974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin *
10974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * Unless required by applicable law or agreed to in writing, software
11974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * distributed under the License is distributed on an "AS IS" BASIS,
12974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * See the License for the specific language governing permissions and
14974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * limitations under the License.
15974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin */
16974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
17974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin#ifndef ANDROID_UTIL_PROTOOUTPUT_STREAM_H
18974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin#define ANDROID_UTIL_PROTOOUTPUT_STREAM_H
19974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
20974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin#include <android/util/EncodedBuffer.h>
21974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
22974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin#include <string>
23974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
24974a9c28853d24ff94f000ae9f5c816d9538897bYi Jinnamespace android {
25974a9c28853d24ff94f000ae9f5c816d9538897bYi Jinnamespace util {
26974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
27974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin/**
285ee0787024cc446a21008ff5710dec19c6afc834Yi Jin * Position of the field type in a 64-bits fieldId.
2904625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin */
3004625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_SHIFT = 32;
3104625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin
3204625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin/**
3304625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin * Mask for the field types stored in a fieldId.  Leaves a whole
3404625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin * byte for future expansion, even though there are currently only 17 types.
3504625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin */
3604625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_MASK = 0x0ffULL << FIELD_TYPE_SHIFT;
3704625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin
38f9ed04b3d938b06329fcd14d4f2b461000d028daYi Jin/**
39f9ed04b3d938b06329fcd14d4f2b461000d028daYi Jin * The types are copied from external/protobuf/src/google/protobuf/descriptor.h directly,
40f9ed04b3d938b06329fcd14d4f2b461000d028daYi Jin * so no extra mapping needs to be maintained in this case.
41f9ed04b3d938b06329fcd14d4f2b461000d028daYi Jin */
4204625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_UNKNOWN  = 0;
4304625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_DOUBLE   = 1ULL << FIELD_TYPE_SHIFT;   // double, exactly eight bytes on the wire.
4404625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_FLOAT    = 2ULL << FIELD_TYPE_SHIFT;   // float, exactly four bytes on the wire.
4504625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_INT64    = 3ULL << FIELD_TYPE_SHIFT;   // int64, varint on the wire.  Negative numbers
4604625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin                                                                 // take 10 bytes.  Use TYPE_SINT64 if negative
4704625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin                                                                 // values are likely.
4804625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_UINT64   = 4ULL << FIELD_TYPE_SHIFT;   // uint64, varint on the wire.
4904625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_INT32    = 5ULL << FIELD_TYPE_SHIFT;   // int32, varint on the wire.  Negative numbers
5004625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin                                                                 // take 10 bytes.  Use TYPE_SINT32 if negative
5104625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin                                                                 // values are likely.
5204625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_FIXED64  = 6ULL << FIELD_TYPE_SHIFT;   // uint64, exactly eight bytes on the wire.
5304625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_FIXED32  = 7ULL << FIELD_TYPE_SHIFT;   // uint32, exactly four bytes on the wire.
5404625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_BOOL     = 8ULL << FIELD_TYPE_SHIFT;   // bool, varint on the wire.
5504625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_STRING   = 9ULL << FIELD_TYPE_SHIFT;   // UTF-8 text.
56f9ed04b3d938b06329fcd14d4f2b461000d028daYi Jin// const uint64_t FIELD_TYPE_GROUP = 10ULL << FIELD_TYPE_SHIFT;  // Tag-delimited message.  Deprecated.
5704625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_MESSAGE  = 11ULL << FIELD_TYPE_SHIFT;  // Length-delimited message.
5804625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin
5904625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_BYTES    = 12ULL << FIELD_TYPE_SHIFT;  // Arbitrary byte array.
6004625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_UINT32   = 13ULL << FIELD_TYPE_SHIFT;  // uint32, varint on the wire
6104625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_ENUM     = 14ULL << FIELD_TYPE_SHIFT;  // Enum, varint on the wire
6204625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_SFIXED32 = 15ULL << FIELD_TYPE_SHIFT;  // int32, exactly four bytes on the wire
6304625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_SFIXED64 = 16ULL << FIELD_TYPE_SHIFT;  // int64, exactly eight bytes on the wire
6404625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_SINT32   = 17ULL << FIELD_TYPE_SHIFT;  // int32, ZigZag-encoded varint on the wire
6504625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_TYPE_SINT64   = 18ULL << FIELD_TYPE_SHIFT;  // int64, ZigZag-encoded varint on the wire
6604625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin
6704625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin//
6804625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin// FieldId flags for whether the field is single, repeated or packed.
6904625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin// TODO: packed is not supported yet.
7004625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin//
7104625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_COUNT_SHIFT = 40;
7204625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_COUNT_MASK = 0x0fULL << FIELD_COUNT_SHIFT;
7304625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_COUNT_UNKNOWN = 0;
7404625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_COUNT_SINGLE = 1ULL << FIELD_COUNT_SHIFT;
7504625ad4886a478bf74bbfc13937c10fa63eb272Yi Jinconst uint64_t FIELD_COUNT_REPEATED = 2ULL << FIELD_COUNT_SHIFT;
76f9ed04b3d938b06329fcd14d4f2b461000d028daYi Jinconst uint64_t FIELD_COUNT_PACKED = 5ULL << FIELD_COUNT_SHIFT;
7704625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin
7804625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin/**
79974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * Class to write to a protobuf stream.
80974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin *
81974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * Each write method takes an ID code from the protoc generated classes
82974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * and the value to write.  To make a nested object, call start
83974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * and then end when you are done.
84974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin *
85974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin * See the java version implementation (ProtoOutputStream.java) for more infos.
86974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin */
87974a9c28853d24ff94f000ae9f5c816d9538897bYi Jinclass ProtoOutputStream
88974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin{
89974a9c28853d24ff94f000ae9f5c816d9538897bYi Jinpublic:
9042711a0b4fffd0dc670ec7bc38cc7f954c60e530Yi Jin    ProtoOutputStream();
91974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    ~ProtoOutputStream();
92974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
93974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    /**
94974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin     * Write APIs for dumping protobuf data. Returns true if the write succeeds.
95974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin     */
96974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool write(uint64_t fieldId, double val);
97974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool write(uint64_t fieldId, float val);
98974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool write(uint64_t fieldId, int val);
99974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool write(uint64_t fieldId, long long val);
100974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool write(uint64_t fieldId, bool val);
101974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool write(uint64_t fieldId, std::string val);
102e08333067a9f4ce9176dff490c4b163f71f56e1eYi Jin    bool write(uint64_t fieldId, const char* val, size_t size);
103974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
104974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    /**
105974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin     * Starts a sub-message write session.
106974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin     * Returns a token of this write session.
107974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin     * Must call end(token) when finish write this sub-message.
108974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin     */
1095ee0787024cc446a21008ff5710dec19c6afc834Yi Jin    uint64_t start(uint64_t fieldId);
1105ee0787024cc446a21008ff5710dec19c6afc834Yi Jin    void end(uint64_t token);
111974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
112974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    /**
1130abdfb0889a4957faaba8a95903e529fced7316cYi Jin     * Returns how many bytes are buffered in ProtoOutputStream.
1140abdfb0889a4957faaba8a95903e529fced7316cYi Jin     * Notice, this is not the actual(compact) size of the output data.
1150abdfb0889a4957faaba8a95903e529fced7316cYi Jin     */
1160abdfb0889a4957faaba8a95903e529fced7316cYi Jin    size_t bytesWritten();
1170abdfb0889a4957faaba8a95903e529fced7316cYi Jin
1180abdfb0889a4957faaba8a95903e529fced7316cYi Jin    /**
11904625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin     * Flushes the protobuf data out to given fd. When the following functions are called,
12004625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin     * it is not able to write to ProtoOutputStream any more since the data is compact.
121974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin     */
12204625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin    size_t size(); // Get the size of the serialized protobuf.
12304625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin    EncodedBuffer::iterator data(); // Get the reader apis of the data.
12404625ad4886a478bf74bbfc13937c10fa63eb272Yi Jin    bool flush(int fd); // Flush data directly to a file descriptor.
12542711a0b4fffd0dc670ec7bc38cc7f954c60e530Yi Jin
1267f9e63b63269baa41a36fc31acd6fc071309c26cYi Jin    /**
1277f9e63b63269baa41a36fc31acd6fc071309c26cYi Jin     * Clears the ProtoOutputStream so the buffer can be reused instead of deallocation/allocation again.
1287f9e63b63269baa41a36fc31acd6fc071309c26cYi Jin     */
1297f9e63b63269baa41a36fc31acd6fc071309c26cYi Jin    void clear();
1307f9e63b63269baa41a36fc31acd6fc071309c26cYi Jin
1318ad193870b2f8d6f8478d591ced2100e22b23229Yi Jin    // Please don't use the following functions to dump protos unless you are familiar with protobuf encoding.
13242711a0b4fffd0dc670ec7bc38cc7f954c60e530Yi Jin    void writeRawVarint(uint64_t varint);
13342711a0b4fffd0dc670ec7bc38cc7f954c60e530Yi Jin    void writeLengthDelimitedHeader(uint32_t id, size_t size);
13442711a0b4fffd0dc670ec7bc38cc7f954c60e530Yi Jin    void writeRawByte(uint8_t byte);
135974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
136974a9c28853d24ff94f000ae9f5c816d9538897bYi Jinprivate:
137974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    EncodedBuffer mBuffer;
138974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    size_t mCopyBegin;
139974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool mCompact;
14000a754499e125c56ed6fae7b9d4eedb6ac7922a8Yi Jin    uint32_t mDepth;
14100a754499e125c56ed6fae7b9d4eedb6ac7922a8Yi Jin    uint32_t mObjectId;
1425ee0787024cc446a21008ff5710dec19c6afc834Yi Jin    uint64_t mExpectedObjectToken;
143974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
144974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeDoubleImpl(uint32_t id, double val);
145974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeFloatImpl(uint32_t id, float val);
146974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeInt64Impl(uint32_t id, long long val);
147974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeInt32Impl(uint32_t id, int val);
148974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeUint64Impl(uint32_t id, uint64_t val);
149974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeUint32Impl(uint32_t id, uint32_t val);
150974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeFixed64Impl(uint32_t id, uint64_t val);
151974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeFixed32Impl(uint32_t id, uint32_t val);
152974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeSFixed64Impl(uint32_t id, long long val);
153974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeSFixed32Impl(uint32_t id, int val);
154974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeZigzagInt64Impl(uint32_t id, long long val);
155974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeZigzagInt32Impl(uint32_t id, int val);
156974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeEnumImpl(uint32_t id, int val);
157974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeBoolImpl(uint32_t id, bool val);
158974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    inline void writeUtf8StringImpl(uint32_t id, const char* val, size_t size);
1598ad193870b2f8d6f8478d591ced2100e22b23229Yi Jin    inline void writeMessageBytesImpl(uint32_t id, const char* val, size_t size);
160974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
161974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool compact();
162974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    size_t editEncodedSize(size_t rawSize);
163974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin    bool compactSize(size_t rawSize);
164974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin};
165974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
166974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin}
167974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin}
168974a9c28853d24ff94f000ae9f5c816d9538897bYi Jin
169e08333067a9f4ce9176dff490c4b163f71f56e1eYi Jin#endif // ANDROID_UTIL_PROTOOUTPUT_STREAM_H
170