Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c60da37 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use c++ template to reduce duped code."

parents ed3c6522 fd2a4c79
Loading
Loading
Loading
Loading
+12 −8
Original line number Original line Diff line number Diff line
@@ -17,10 +17,11 @@
#ifndef ANDROID_UTIL_PROTOOUTPUT_STREAM_H
#ifndef ANDROID_UTIL_PROTOOUTPUT_STREAM_H
#define ANDROID_UTIL_PROTOOUTPUT_STREAM_H
#define ANDROID_UTIL_PROTOOUTPUT_STREAM_H


#include <android/util/EncodedBuffer.h>
#include <cstdint>

#include <string>
#include <string>


#include <android/util/EncodedBuffer.h>

namespace android {
namespace android {
namespace util {
namespace util {


@@ -143,16 +144,16 @@ private:


    inline void writeDoubleImpl(uint32_t id, double val);
    inline void writeDoubleImpl(uint32_t id, double val);
    inline void writeFloatImpl(uint32_t id, float val);
    inline void writeFloatImpl(uint32_t id, float val);
    inline void writeInt64Impl(uint32_t id, long long val);
    inline void writeInt64Impl(uint32_t id, int64_t val);
    inline void writeInt32Impl(uint32_t id, int val);
    inline void writeInt32Impl(uint32_t id, int32_t val);
    inline void writeUint64Impl(uint32_t id, uint64_t val);
    inline void writeUint64Impl(uint32_t id, uint64_t val);
    inline void writeUint32Impl(uint32_t id, uint32_t val);
    inline void writeUint32Impl(uint32_t id, uint32_t val);
    inline void writeFixed64Impl(uint32_t id, uint64_t val);
    inline void writeFixed64Impl(uint32_t id, uint64_t val);
    inline void writeFixed32Impl(uint32_t id, uint32_t val);
    inline void writeFixed32Impl(uint32_t id, uint32_t val);
    inline void writeSFixed64Impl(uint32_t id, long long val);
    inline void writeSFixed64Impl(uint32_t id, int64_t val);
    inline void writeSFixed32Impl(uint32_t id, int val);
    inline void writeSFixed32Impl(uint32_t id, int32_t val);
    inline void writeZigzagInt64Impl(uint32_t id, long long val);
    inline void writeZigzagInt64Impl(uint32_t id, int64_t val);
    inline void writeZigzagInt32Impl(uint32_t id, int val);
    inline void writeZigzagInt32Impl(uint32_t id, int32_t val);
    inline void writeEnumImpl(uint32_t id, int val);
    inline void writeEnumImpl(uint32_t id, int val);
    inline void writeBoolImpl(uint32_t id, bool val);
    inline void writeBoolImpl(uint32_t id, bool val);
    inline void writeUtf8StringImpl(uint32_t id, const char* val, size_t size);
    inline void writeUtf8StringImpl(uint32_t id, const char* val, size_t size);
@@ -161,6 +162,9 @@ private:
    bool compact();
    bool compact();
    size_t editEncodedSize(size_t rawSize);
    size_t editEncodedSize(size_t rawSize);
    bool compactSize(size_t rawSize);
    bool compactSize(size_t rawSize);

    template<typename T>
    bool internalWrite(uint64_t fieldId, T val, const char* typeName);
};
};


}
}
+56 −94
Original line number Original line Diff line number Diff line
@@ -15,7 +15,8 @@
 */
 */
#define LOG_TAG "libprotoutil"
#define LOG_TAG "libprotoutil"


#include <inttypes.h>
#include <cinttypes>
#include <type_traits>


#include <android-base/file.h>
#include <android-base/file.h>
#include <android/util/protobuf.h>
#include <android/util/protobuf.h>
@@ -51,112 +52,73 @@ ProtoOutputStream::clear()
    mExpectedObjectToken = UINT64_C(-1);
    mExpectedObjectToken = UINT64_C(-1);
}
}


template<typename T>
bool
bool
ProtoOutputStream::write(uint64_t fieldId, double val)
ProtoOutputStream::internalWrite(uint64_t fieldId, T val, const char* typeName)
{
{
    if (mCompact) return false;
    if (mCompact) return false;
    const uint32_t id = (uint32_t)fieldId;
    const uint32_t id = (uint32_t)fieldId;
    switch (fieldId & FIELD_TYPE_MASK) {
    switch (fieldId & FIELD_TYPE_MASK) {
        case FIELD_TYPE_DOUBLE:   writeDoubleImpl(id, (double)val);           break;
        case FIELD_TYPE_DOUBLE:   writeDoubleImpl(id, (double)val);           break;
        case FIELD_TYPE_FLOAT:    writeFloatImpl(id, (float)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_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_FIXED64:  writeFixed64Impl(id, (uint64_t)val);        break;
        case FIELD_TYPE_FIXED32:  writeFixed32Impl(id, (uint32_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_UINT32:   writeUint32Impl(id, (uint32_t)val);         break;
        case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val);            break;
        case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int32_t)val);        break;
        case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val);      break;
        case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (int64_t)val);        break;
        case FIELD_TYPE_SINT32:   writeZigzagInt32Impl(id, (int)val);         break;
        case FIELD_TYPE_SINT32:   writeZigzagInt32Impl(id, (int32_t)val);     break;
        case FIELD_TYPE_SINT64:   writeZigzagInt64Impl(id, (long long)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:
        default:
            ALOGW("Field type %d is not supported when writing double val.",
            goto unsupported;
                    (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
            return false;
    }
    }
    return true;
    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
bool
ProtoOutputStream::write(uint64_t fieldId, float val)
ProtoOutputStream::write(uint64_t fieldId, double val)
{
{
    if (mCompact) return false;
    return internalWrite(fieldId, val, "double");
    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;


bool
ProtoOutputStream::write(uint64_t fieldId, float val)
{
    return internalWrite(fieldId, val, "float");
}
}


bool
bool
ProtoOutputStream::write(uint64_t fieldId, int val)
ProtoOutputStream::write(uint64_t fieldId, int val)
{
{
    if (mCompact) return false;
    return internalWrite(fieldId, val, "int");
    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;
}
}


bool
bool
ProtoOutputStream::write(uint64_t fieldId, long long val)
ProtoOutputStream::write(uint64_t fieldId, long long val)
{
{
    if (mCompact) return false;
    return internalWrite(fieldId, val, "long long");
    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;
}
}


bool
bool
@@ -169,8 +131,8 @@ ProtoOutputStream::write(uint64_t fieldId, bool val)
            writeBoolImpl(id, val);
            writeBoolImpl(id, val);
            return true;
            return true;
        default:
        default:
            ALOGW("Field type %d is not supported when writing bool val.",
            ALOGW("Field type %" PRIu64 " is not supported when writing bool val.",
                    (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
                    (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
            return false;
            return false;
    }
    }
}
}
@@ -185,8 +147,8 @@ ProtoOutputStream::write(uint64_t fieldId, std::string val)
            writeUtf8StringImpl(id, val.c_str(), val.size());
            writeUtf8StringImpl(id, val.c_str(), val.size());
            return true;
            return true;
        default:
        default:
            ALOGW("Field type %d is not supported when writing string val.",
            ALOGW("Field type %" PRIu64 " is not supported when writing string val.",
                    (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
                    (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
            return false;
            return false;
    }
    }
}
}
@@ -206,8 +168,8 @@ ProtoOutputStream::write(uint64_t fieldId, const char* val, size_t size)
            writeMessageBytesImpl(id, val, size);
            writeMessageBytesImpl(id, val, size);
            return true;
            return true;
        default:
        default:
            ALOGW("Field type %d is not supported when writing char[] val.",
            ALOGW("Field type %" PRIu64 " is not supported when writing char[] val.",
                    (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
                    (fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT);
            return false;
            return false;
    }
    }
}
}
@@ -542,17 +504,17 @@ ProtoOutputStream::writeFloatImpl(uint32_t id, float val)
}
}


inline void
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.writeHeader(id, WIRE_TYPE_VARINT);
    mBuffer.writeRawVarint64((uint64_t)val);
    mBuffer.writeRawVarint64(val);
}
}


inline void
inline void
ProtoOutputStream::writeInt32Impl(uint32_t id, int val)
ProtoOutputStream::writeInt32Impl(uint32_t id, int32_t val)
{
{
    mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
    mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
    mBuffer.writeRawVarint32((uint32_t)val);
    mBuffer.writeRawVarint32(val);
}
}


inline void
inline void
@@ -584,28 +546,28 @@ ProtoOutputStream::writeFixed32Impl(uint32_t id, uint32_t val)
}
}


inline void
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.writeHeader(id, WIRE_TYPE_FIXED64);
    mBuffer.writeRawFixed64((uint64_t)val);
    mBuffer.writeRawFixed64(val);
}
}


inline void
inline void
ProtoOutputStream::writeSFixed32Impl(uint32_t id, int val)
ProtoOutputStream::writeSFixed32Impl(uint32_t id, int32_t val)
{
{
    mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
    mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
    mBuffer.writeRawFixed32((uint32_t)val);
    mBuffer.writeRawFixed32(val);
}
}


inline void
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.writeHeader(id, WIRE_TYPE_VARINT);
    mBuffer.writeRawVarint64((val << 1) ^ (val >> 63));
    mBuffer.writeRawVarint64((val << 1) ^ (val >> 63));
}
}


inline void
inline void
ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int val)
ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int32_t val)
{
{
    mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
    mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
    mBuffer.writeRawVarint32((val << 1) ^ (val >> 31));
    mBuffer.writeRawVarint32((val << 1) ^ (val >> 31));
+25 −3
Original line number Original line Diff line number Diff line
@@ -132,17 +132,31 @@ TEST(ProtoOutputStreamTest, Reusability) {
    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 15));
    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 15));
    EXPECT_EQ(proto.bytesWritten(), 4);
    EXPECT_EQ(proto.bytesWritten(), 4);
    EXPECT_EQ(proto.size(), 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();
    proto.clear();
    EXPECT_EQ(proto.bytesWritten(), 0);
    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) {
TEST(ProtoOutputStreamTest, AdvancedEncoding) {
    ProtoOutputStream proto;
    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.writeRawVarint(UINT64_C(-123809234));
    proto.writeLengthDelimitedHeader(ComplexProto::kLogsFieldNumber, 8);
    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(6);
    proto.writeRawByte('b');
    proto.writeRawByte('b');
    proto.writeRawByte('a');
    proto.writeRawByte('a');
@@ -168,3 +182,11 @@ TEST(ProtoOutputStreamTest, AdvancedEncoding) {
    EXPECT_FALSE(log2.has_name());
    EXPECT_FALSE(log2.has_name());
    EXPECT_FALSE(log2.has_data());
    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