1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_UTIL_PROTOOUTPUT_STREAM_H 18 #define ANDROID_UTIL_PROTOOUTPUT_STREAM_H 19 20 #include <android/util/EncodedBuffer.h> 21 22 #include <string> 23 24 namespace android { 25 namespace util { 26 27 /** 28 * Position of the field type in a 64-bits fieldId. 29 */ 30 const uint64_t FIELD_TYPE_SHIFT = 32; 31 32 /** 33 * Mask for the field types stored in a fieldId. Leaves a whole 34 * byte for future expansion, even though there are currently only 17 types. 35 */ 36 const uint64_t FIELD_TYPE_MASK = 0x0ffULL << FIELD_TYPE_SHIFT; 37 38 /** 39 * The types are copied from external/protobuf/src/google/protobuf/descriptor.h directly, 40 * so no extra mapping needs to be maintained in this case. 41 */ 42 const uint64_t FIELD_TYPE_UNKNOWN = 0; 43 const uint64_t FIELD_TYPE_DOUBLE = 1ULL << FIELD_TYPE_SHIFT; // double, exactly eight bytes on the wire. 44 const uint64_t FIELD_TYPE_FLOAT = 2ULL << FIELD_TYPE_SHIFT; // float, exactly four bytes on the wire. 45 const uint64_t FIELD_TYPE_INT64 = 3ULL << FIELD_TYPE_SHIFT; // int64, varint on the wire. Negative numbers 46 // take 10 bytes. Use TYPE_SINT64 if negative 47 // values are likely. 48 const uint64_t FIELD_TYPE_UINT64 = 4ULL << FIELD_TYPE_SHIFT; // uint64, varint on the wire. 49 const uint64_t FIELD_TYPE_INT32 = 5ULL << FIELD_TYPE_SHIFT; // int32, varint on the wire. Negative numbers 50 // take 10 bytes. Use TYPE_SINT32 if negative 51 // values are likely. 52 const uint64_t FIELD_TYPE_FIXED64 = 6ULL << FIELD_TYPE_SHIFT; // uint64, exactly eight bytes on the wire. 53 const uint64_t FIELD_TYPE_FIXED32 = 7ULL << FIELD_TYPE_SHIFT; // uint32, exactly four bytes on the wire. 54 const uint64_t FIELD_TYPE_BOOL = 8ULL << FIELD_TYPE_SHIFT; // bool, varint on the wire. 55 const uint64_t FIELD_TYPE_STRING = 9ULL << FIELD_TYPE_SHIFT; // UTF-8 text. 56 // const uint64_t FIELD_TYPE_GROUP = 10ULL << FIELD_TYPE_SHIFT; // Tag-delimited message. Deprecated. 57 const uint64_t FIELD_TYPE_MESSAGE = 11ULL << FIELD_TYPE_SHIFT; // Length-delimited message. 58 59 const uint64_t FIELD_TYPE_BYTES = 12ULL << FIELD_TYPE_SHIFT; // Arbitrary byte array. 60 const uint64_t FIELD_TYPE_UINT32 = 13ULL << FIELD_TYPE_SHIFT; // uint32, varint on the wire 61 const uint64_t FIELD_TYPE_ENUM = 14ULL << FIELD_TYPE_SHIFT; // Enum, varint on the wire 62 const uint64_t FIELD_TYPE_SFIXED32 = 15ULL << FIELD_TYPE_SHIFT; // int32, exactly four bytes on the wire 63 const uint64_t FIELD_TYPE_SFIXED64 = 16ULL << FIELD_TYPE_SHIFT; // int64, exactly eight bytes on the wire 64 const uint64_t FIELD_TYPE_SINT32 = 17ULL << FIELD_TYPE_SHIFT; // int32, ZigZag-encoded varint on the wire 65 const uint64_t FIELD_TYPE_SINT64 = 18ULL << FIELD_TYPE_SHIFT; // int64, ZigZag-encoded varint on the wire 66 67 // 68 // FieldId flags for whether the field is single, repeated or packed. 69 // TODO: packed is not supported yet. 70 // 71 const uint64_t FIELD_COUNT_SHIFT = 40; 72 const uint64_t FIELD_COUNT_MASK = 0x0fULL << FIELD_COUNT_SHIFT; 73 const uint64_t FIELD_COUNT_UNKNOWN = 0; 74 const uint64_t FIELD_COUNT_SINGLE = 1ULL << FIELD_COUNT_SHIFT; 75 const uint64_t FIELD_COUNT_REPEATED = 2ULL << FIELD_COUNT_SHIFT; 76 const uint64_t FIELD_COUNT_PACKED = 5ULL << FIELD_COUNT_SHIFT; 77 78 /** 79 * Class to write to a protobuf stream. 80 * 81 * Each write method takes an ID code from the protoc generated classes 82 * and the value to write. To make a nested object, call start 83 * and then end when you are done. 84 * 85 * See the java version implementation (ProtoOutputStream.java) for more infos. 86 */ 87 class ProtoOutputStream 88 { 89 public: 90 ProtoOutputStream(); 91 ~ProtoOutputStream(); 92 93 /** 94 * Write APIs for dumping protobuf data. Returns true if the write succeeds. 95 */ 96 bool write(uint64_t fieldId, double val); 97 bool write(uint64_t fieldId, float val); 98 bool write(uint64_t fieldId, int val); 99 bool write(uint64_t fieldId, long long val); 100 bool write(uint64_t fieldId, bool val); 101 bool write(uint64_t fieldId, std::string val); 102 bool write(uint64_t fieldId, const char* val, size_t size); 103 104 /** 105 * Starts a sub-message write session. 106 * Returns a token of this write session. 107 * Must call end(token) when finish write this sub-message. 108 */ 109 uint64_t start(uint64_t fieldId); 110 void end(uint64_t token); 111 112 /** 113 * Returns how many bytes are buffered in ProtoOutputStream. 114 * Notice, this is not the actual(compact) size of the output data. 115 */ 116 size_t bytesWritten(); 117 118 /** 119 * Flushes the protobuf data out to given fd. When the following functions are called, 120 * it is not able to write to ProtoOutputStream any more since the data is compact. 121 */ 122 size_t size(); // Get the size of the serialized protobuf. 123 EncodedBuffer::iterator data(); // Get the reader apis of the data. 124 bool flush(int fd); // Flush data directly to a file descriptor. 125 126 /** 127 * Clears the ProtoOutputStream so the buffer can be reused instead of deallocation/allocation again. 128 */ 129 void clear(); 130 131 // Please don't use the following functions to dump protos unless you are familiar with protobuf encoding. 132 void writeRawVarint(uint64_t varint); 133 void writeLengthDelimitedHeader(uint32_t id, size_t size); 134 void writeRawByte(uint8_t byte); 135 136 private: 137 EncodedBuffer mBuffer; 138 size_t mCopyBegin; 139 bool mCompact; 140 uint32_t mDepth; 141 uint32_t mObjectId; 142 uint64_t mExpectedObjectToken; 143 144 inline void writeDoubleImpl(uint32_t id, double val); 145 inline void writeFloatImpl(uint32_t id, float val); 146 inline void writeInt64Impl(uint32_t id, long long val); 147 inline void writeInt32Impl(uint32_t id, int val); 148 inline void writeUint64Impl(uint32_t id, uint64_t val); 149 inline void writeUint32Impl(uint32_t id, uint32_t val); 150 inline void writeFixed64Impl(uint32_t id, uint64_t val); 151 inline void writeFixed32Impl(uint32_t id, uint32_t val); 152 inline void writeSFixed64Impl(uint32_t id, long long val); 153 inline void writeSFixed32Impl(uint32_t id, int val); 154 inline void writeZigzagInt64Impl(uint32_t id, long long val); 155 inline void writeZigzagInt32Impl(uint32_t id, int val); 156 inline void writeEnumImpl(uint32_t id, int val); 157 inline void writeBoolImpl(uint32_t id, bool val); 158 inline void writeUtf8StringImpl(uint32_t id, const char* val, size_t size); 159 inline void writeMessageBytesImpl(uint32_t id, const char* val, size_t size); 160 161 bool compact(); 162 size_t editEncodedSize(size_t rawSize); 163 bool compactSize(size_t rawSize); 164 }; 165 166 } 167 } 168 169 #endif // ANDROID_UTIL_PROTOOUTPUT_STREAM_H 170