diff options
author | Yi Jin <jinyithu@google.com> | 2018-04-26 11:49:08 -0700 |
---|---|---|
committer | Yi Jin <jinyithu@google.com> | 2018-04-26 14:28:12 -0700 |
commit | fd2a4c791e59841fd2ab664b335168f910cbf309 (patch) | |
tree | ffccbb279b5b7da9f30e343a347aadefc8d57d93 /libs/protoutil | |
parent | 4afbedf988425e25b74e3d246cbefaff9e10c1bb (diff) |
Use c++ template to reduce duped code.
Bug: 77342154
Test: atest libprotoutil_test
Change-Id: I6cf165c2214a8a627722a156b7498d0d8f5d1e18
Diffstat (limited to 'libs/protoutil')
-rw-r--r-- | libs/protoutil/include/android/util/ProtoOutputStream.h | 20 | ||||
-rw-r--r-- | libs/protoutil/src/ProtoOutputStream.cpp | 150 | ||||
-rw-r--r-- | libs/protoutil/tests/ProtoOutputStream_test.cpp | 28 |
3 files changed, 93 insertions, 105 deletions
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h index e17f48b98037..ad90893f8cd6 100644 --- a/libs/protoutil/include/android/util/ProtoOutputStream.h +++ b/libs/protoutil/include/android/util/ProtoOutputStream.h @@ -17,10 +17,11 @@ #ifndef ANDROID_UTIL_PROTOOUTPUT_STREAM_H #define ANDROID_UTIL_PROTOOUTPUT_STREAM_H -#include <android/util/EncodedBuffer.h> - +#include <cstdint> #include <string> +#include <android/util/EncodedBuffer.h> + namespace android { namespace util { @@ -143,16 +144,16 @@ private: inline void writeDoubleImpl(uint32_t id, double val); inline void writeFloatImpl(uint32_t id, float val); - inline void writeInt64Impl(uint32_t id, long long val); - inline void writeInt32Impl(uint32_t id, int val); + inline void writeInt64Impl(uint32_t id, int64_t val); + inline void writeInt32Impl(uint32_t id, int32_t val); inline void writeUint64Impl(uint32_t id, uint64_t val); inline void writeUint32Impl(uint32_t id, uint32_t val); inline void writeFixed64Impl(uint32_t id, uint64_t val); inline void writeFixed32Impl(uint32_t id, uint32_t val); - inline void writeSFixed64Impl(uint32_t id, long long val); - inline void writeSFixed32Impl(uint32_t id, int val); - inline void writeZigzagInt64Impl(uint32_t id, long long val); - inline void writeZigzagInt32Impl(uint32_t id, int val); + inline void writeSFixed64Impl(uint32_t id, int64_t val); + inline void writeSFixed32Impl(uint32_t id, int32_t val); + inline void writeZigzagInt64Impl(uint32_t id, int64_t val); + inline void writeZigzagInt32Impl(uint32_t id, int32_t val); inline void writeEnumImpl(uint32_t id, int val); inline void writeBoolImpl(uint32_t id, bool val); inline void writeUtf8StringImpl(uint32_t id, const char* val, size_t size); @@ -161,6 +162,9 @@ private: bool compact(); size_t editEncodedSize(size_t rawSize); bool compactSize(size_t rawSize); + + template<typename T> + bool internalWrite(uint64_t fieldId, T val, const char* typeName); }; } diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp index 3fee7e42338d..0d429e0ba6c8 100644 --- a/libs/protoutil/src/ProtoOutputStream.cpp +++ b/libs/protoutil/src/ProtoOutputStream.cpp @@ -15,7 +15,8 @@ */ #define LOG_TAG "libprotoutil" -#include <inttypes.h> +#include <cinttypes> +#include <type_traits> #include <android-base/file.h> #include <android/util/protobuf.h> @@ -51,112 +52,73 @@ ProtoOutputStream::clear() mExpectedObjectToken = UINT64_C(-1); } +template<typename T> bool -ProtoOutputStream::write(uint64_t fieldId, double val) +ProtoOutputStream::internalWrite(uint64_t fieldId, T val, const char* typeName) { if (mCompact) return false; const uint32_t id = (uint32_t)fieldId; switch (fieldId & FIELD_TYPE_MASK) { case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break; case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break; - case FIELD_TYPE_INT64: writeInt64Impl(id, (long long)val); break; + case FIELD_TYPE_INT64: writeInt64Impl(id, (int64_t)val); break; case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break; - case FIELD_TYPE_INT32: writeInt32Impl(id, (int)val); break; + case FIELD_TYPE_INT32: writeInt32Impl(id, (int32_t)val); break; case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break; case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break; case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break; - case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break; - case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break; - case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break; - case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break; + case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int32_t)val); break; + case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (int64_t)val); break; + case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int32_t)val); break; + case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (int64_t)val); break; + case FIELD_TYPE_ENUM: + if (std::is_integral<T>::value) { + writeEnumImpl(id, (int)val); + } else { + goto unsupported; + } + break; + case FIELD_TYPE_BOOL: + if (std::is_integral<T>::value) { + writeBoolImpl(id, val != 0); + } else { + goto unsupported; + } + break; default: - ALOGW("Field type %d is not supported when writing double val.", - (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); - return false; + goto unsupported; } return true; + +unsupported: + ALOGW("Field type %" PRIu64 " is not supported when writing %s val.", + (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT, typeName); + return false; +} + +bool +ProtoOutputStream::write(uint64_t fieldId, double val) +{ + return internalWrite(fieldId, val, "double"); } + bool ProtoOutputStream::write(uint64_t fieldId, float val) { - if (mCompact) return false; - const uint32_t id = (uint32_t)fieldId; - switch (fieldId & FIELD_TYPE_MASK) { - case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break; - case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break; - case FIELD_TYPE_INT64: writeInt64Impl(id, (long long)val); break; - case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break; - case FIELD_TYPE_INT32: writeInt32Impl(id, (int)val); break; - case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break; - case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break; - case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break; - case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break; - case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break; - case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break; - case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break; - default: - ALOGW("Field type %d is not supported when writing float val.", - (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); - return false; - } - return true; + return internalWrite(fieldId, val, "float"); } bool ProtoOutputStream::write(uint64_t fieldId, int val) { - if (mCompact) return false; - const uint32_t id = (uint32_t)fieldId; - switch (fieldId & FIELD_TYPE_MASK) { - case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break; - case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break; - case FIELD_TYPE_INT64: writeInt64Impl(id, (long long)val); break; - case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break; - case FIELD_TYPE_INT32: writeInt32Impl(id, (int)val); break; - case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break; - case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break; - case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break; - case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break; - case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break; - case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break; - case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break; - case FIELD_TYPE_ENUM: writeEnumImpl(id, (int)val); break; - case FIELD_TYPE_BOOL: writeBoolImpl(id, val != 0); break; - default: - ALOGW("Field type %d is not supported when writing int val.", - (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); - return false; - } - return true; + return internalWrite(fieldId, val, "int"); } bool ProtoOutputStream::write(uint64_t fieldId, long long val) { - if (mCompact) return false; - const uint32_t id = (uint32_t)fieldId; - switch (fieldId & FIELD_TYPE_MASK) { - case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break; - case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break; - case FIELD_TYPE_INT64: writeInt64Impl(id, (long long)val); break; - case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break; - case FIELD_TYPE_INT32: writeInt32Impl(id, (int)val); break; - case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break; - case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break; - case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break; - case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break; - case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break; - case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break; - case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break; - case FIELD_TYPE_ENUM: writeEnumImpl(id, (int)val); break; - case FIELD_TYPE_BOOL: writeBoolImpl(id, val != 0); break; - default: - ALOGW("Field type %d is not supported when writing long long val.", - (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); - return false; - } - return true; + return internalWrite(fieldId, val, "long long"); } bool @@ -169,8 +131,8 @@ ProtoOutputStream::write(uint64_t fieldId, bool val) writeBoolImpl(id, val); return true; default: - ALOGW("Field type %d is not supported when writing bool val.", - (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); + ALOGW("Field type %" PRIu64 " is not supported when writing bool val.", + (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT); return false; } } @@ -185,8 +147,8 @@ ProtoOutputStream::write(uint64_t fieldId, std::string val) writeUtf8StringImpl(id, val.c_str(), val.size()); return true; default: - ALOGW("Field type %d is not supported when writing string val.", - (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); + ALOGW("Field type %" PRIu64 " is not supported when writing string val.", + (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT); return false; } } @@ -206,8 +168,8 @@ ProtoOutputStream::write(uint64_t fieldId, const char* val, size_t size) writeMessageBytesImpl(id, val, size); return true; default: - ALOGW("Field type %d is not supported when writing char[] val.", - (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); + ALOGW("Field type %" PRIu64 " is not supported when writing char[] val.", + (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT); return false; } } @@ -542,17 +504,17 @@ ProtoOutputStream::writeFloatImpl(uint32_t id, float val) } inline void -ProtoOutputStream::writeInt64Impl(uint32_t id, long long val) +ProtoOutputStream::writeInt64Impl(uint32_t id, int64_t val) { mBuffer.writeHeader(id, WIRE_TYPE_VARINT); - mBuffer.writeRawVarint64((uint64_t)val); + mBuffer.writeRawVarint64(val); } inline void -ProtoOutputStream::writeInt32Impl(uint32_t id, int val) +ProtoOutputStream::writeInt32Impl(uint32_t id, int32_t val) { mBuffer.writeHeader(id, WIRE_TYPE_VARINT); - mBuffer.writeRawVarint32((uint32_t)val); + mBuffer.writeRawVarint32(val); } inline void @@ -584,28 +546,28 @@ ProtoOutputStream::writeFixed32Impl(uint32_t id, uint32_t val) } inline void -ProtoOutputStream::writeSFixed64Impl(uint32_t id, long long val) +ProtoOutputStream::writeSFixed64Impl(uint32_t id, int64_t val) { mBuffer.writeHeader(id, WIRE_TYPE_FIXED64); - mBuffer.writeRawFixed64((uint64_t)val); + mBuffer.writeRawFixed64(val); } inline void -ProtoOutputStream::writeSFixed32Impl(uint32_t id, int val) +ProtoOutputStream::writeSFixed32Impl(uint32_t id, int32_t val) { mBuffer.writeHeader(id, WIRE_TYPE_FIXED32); - mBuffer.writeRawFixed32((uint32_t)val); + mBuffer.writeRawFixed32(val); } inline void -ProtoOutputStream::writeZigzagInt64Impl(uint32_t id, long long val) +ProtoOutputStream::writeZigzagInt64Impl(uint32_t id, int64_t val) { mBuffer.writeHeader(id, WIRE_TYPE_VARINT); mBuffer.writeRawVarint64((val << 1) ^ (val >> 63)); } inline void -ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int val) +ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int32_t val) { mBuffer.writeHeader(id, WIRE_TYPE_VARINT); mBuffer.writeRawVarint32((val << 1) ^ (val >> 31)); diff --git a/libs/protoutil/tests/ProtoOutputStream_test.cpp b/libs/protoutil/tests/ProtoOutputStream_test.cpp index e8e155779829..5c25787e8555 100644 --- a/libs/protoutil/tests/ProtoOutputStream_test.cpp +++ b/libs/protoutil/tests/ProtoOutputStream_test.cpp @@ -132,17 +132,31 @@ TEST(ProtoOutputStreamTest, Reusability) { EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 15)); EXPECT_EQ(proto.bytesWritten(), 4); EXPECT_EQ(proto.size(), 4); + // Can't write to proto after compact + EXPECT_FALSE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 94)); + + ComplexProto beforeClear; + ASSERT_TRUE(beforeClear.ParseFromString(flushToString(&proto))); + EXPECT_EQ(beforeClear.ints_size(), 2); + EXPECT_EQ(beforeClear.ints(0), 32); + EXPECT_EQ(beforeClear.ints(1), 15); + proto.clear(); EXPECT_EQ(proto.bytesWritten(), 0); - EXPECT_EQ(proto.size(), 0); + EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 1076)); + + ComplexProto afterClear; + ASSERT_TRUE(afterClear.ParseFromString(flushToString(&proto))); + EXPECT_EQ(afterClear.ints_size(), 1); + EXPECT_EQ(afterClear.ints(0), 1076); } TEST(ProtoOutputStreamTest, AdvancedEncoding) { ProtoOutputStream proto; - proto.writeRawVarint(ComplexProto::kIntsFieldNumber << FIELD_ID_SHIFT); + proto.writeRawVarint((ComplexProto::kIntsFieldNumber << FIELD_ID_SHIFT) + WIRE_TYPE_VARINT); proto.writeRawVarint(UINT64_C(-123809234)); proto.writeLengthDelimitedHeader(ComplexProto::kLogsFieldNumber, 8); - proto.writeRawByte((ComplexProto::Log::kDataFieldNumber << FIELD_ID_SHIFT) + 2); + proto.writeRawByte((ComplexProto::Log::kDataFieldNumber << FIELD_ID_SHIFT) + WIRE_TYPE_LENGTH_DELIMITED); proto.writeRawByte(6); proto.writeRawByte('b'); proto.writeRawByte('a'); @@ -168,3 +182,11 @@ TEST(ProtoOutputStreamTest, AdvancedEncoding) { EXPECT_FALSE(log2.has_name()); EXPECT_FALSE(log2.has_data()); } + +TEST(ProtoOutputStreamTest, InvalidTypes) { + ProtoOutputStream proto; + EXPECT_FALSE(proto.write(FIELD_TYPE_UNKNOWN | PrimitiveProto::kValInt32FieldNumber, 790)); + EXPECT_FALSE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 234.34)); + EXPECT_FALSE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, 18.73f)); + EXPECT_EQ(proto.size(), 0); +}
\ No newline at end of file |