Protobuf: Store the full message name in char_data

And store the size of the message name in the Data section.
Adding more meta data can be done in a similar way, adding extra fields
to char_data, bumping the version field and updating char_data() to deal
with new data.

Change-Id: Id7d3d867d74bcc80a05e597a4d0af7056982accb
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Mårten Nordheim 2022-11-23 13:42:59 +01:00
parent 41e980af0d
commit 122625ed30
8 changed files with 90 additions and 20 deletions

View File

@ -20,6 +20,13 @@ namespace QtProtobufPrivate {
constexpr uint jsonNameOffsetsOffset = 0;
// Use this constant to make the +/- 1 more easily readable
constexpr int NullTerminator = 1;
QUtf8StringView QProtobufPropertyOrdering::getMessageFullName() const
{
Q_ASSERT(data);
const char *name = char_data();
return { name, qsizetype(data->fullPackageNameSize) };
}
QUtf8StringView QProtobufPropertyOrdering::getJsonName(int index) const
{
Q_ASSERT(data);
@ -86,8 +93,7 @@ namespace QtProtobufPrivate {
{
Q_ASSERT(data);
const uint LastOffset = data->flagsOffset;
const uint *u_data = &uint_dataForIndex(int(data->numFields - 1), LastOffset);
++u_data;
const uint *u_data = uint_data() + LastOffset + data->numFields;
quintptr uptr_data = quintptr(u_data);
if (size_t(uptr_data) % alignof(char) != 0)
uptr_data += alignof(char) - size_t(uptr_data) % alignof(char);

View File

@ -32,8 +32,10 @@ struct QProtobufPropertyOrdering
uint fieldNumberOffset;
uint propertyIndexOffset;
uint flagsOffset;
uint fullPackageNameSize;
} *data;
Q_PROTOBUF_EXPORT QUtf8StringView getMessageFullName() const;
Q_PROTOBUF_EXPORT QUtf8StringView getJsonName(int index) const;
Q_PROTOBUF_EXPORT int getFieldNumber(int index) const;
Q_PROTOBUF_EXPORT int getPropertyIndex(int index) const;

View File

@ -89,22 +89,25 @@ void MessageDefinitionPrinter::printFieldsOrdering()
const int fieldCount = m_descriptor->field_count();
constexpr int MetaFieldsCount = 4;
constexpr int Version = 0;
constexpr int NullTerminator = 1;
constexpr int FakeJsonNameOffset = 1;
int uint_dataOffset = 1; // the json name offsets are always stored at offset 0
auto char_dataSize = charDataSize();
int uint_dataOffset = 1;
size_t metadataCharSize = metaCharDataSize();
size_t char_dataSize = charDataSize();
size_t char_dataSizeTotal = metadataCharSize + NullTerminator + char_dataSize;
std::map<std::string, std::string> dataVariables = {
{ "version_number", std::to_string(Version) },
{ "classname", m_typeMap["classname"] },
{ "num_fields", std::to_string(fieldCount) },
// +1 for EOS offset in JSON data
{ "field_number_offset", std::to_string(fieldCount * (uint_dataOffset++) + 1) },
// +1 for EOS offset in JSON data
{ "property_index_offset", std::to_string(fieldCount * (uint_dataOffset++) + 1) },
// +1 for EOS offset in JSON data
{ "field_flags_offset", std::to_string(fieldCount * (uint_dataOffset++) + 1) },
// +1 for EOS offset in JSON data
{ "uint_size", std::to_string(fieldCount * MetaFieldsCount + 1) },
{ "char_size", std::to_string(char_dataSize) },
{ "field_number_offset",
std::to_string(fieldCount * (uint_dataOffset++) + NullTerminator) },
{ "property_index_offset",
std::to_string(fieldCount * (uint_dataOffset++) + NullTerminator) },
{ "field_flags_offset", std::to_string(fieldCount * (uint_dataOffset++) + NullTerminator) },
{ "uint_size", std::to_string(fieldCount * MetaFieldsCount + FakeJsonNameOffset) },
{ "char_size", std::to_string(char_dataSizeTotal) },
{ "message_full_name_size", std::to_string(metadataCharSize) },
};
assert(uint_dataOffset == MetaFieldsCount);
@ -118,7 +121,7 @@ void MessageDefinitionPrinter::printFieldsOrdering()
printUintData(Templates::JsonNameOffsetsUintDataTemplate());
// Include an extra offset which points to the end-of-string, so we can efficiently get the
// length of all the strings by subtracting adjacent offsets:
m_printer->Print({ { "json_name_offset", std::to_string(char_dataSize - 1) },
m_printer->Print({ { "json_name_offset", std::to_string(char_dataSizeTotal - NullTerminator) },
{ "json_name", "end-of-string-marker" } },
Templates::JsonNameOffsetsUintDataTemplate());
@ -135,9 +138,7 @@ void MessageDefinitionPrinter::printFieldsOrdering()
m_printer->Print("},\n");
// char_data
m_printer->Print("// char_data\n\"");
printCharData();
m_printer->Print("\"\n");
Outdent();
m_printer->Print(m_typeMap, Templates::PropertyOrderingDataClosingTemplate());
@ -147,7 +148,9 @@ void MessageDefinitionPrinter::printFieldsOrdering()
void MessageDefinitionPrinter::printUintData(const char *templateString)
{
size_t jsonOffset = 0;
constexpr size_t NullTerminator = 1;
// JSon data starts where string metadata ends
size_t jsonOffset = metaCharDataSize() + NullTerminator;
int index = 0;
const int numFields = m_descriptor->field_count();
for (int i = 0; i < numFields; ++i) {
@ -162,12 +165,19 @@ void MessageDefinitionPrinter::printUintData(const char *templateString)
m_printer->Print(variables, templateString);
const size_t length = field->json_name().length();
jsonOffset += length + 1; // +1 for the embedded null terminator
jsonOffset += length + NullTerminator;
}
}
void MessageDefinitionPrinter::printCharData()
{
m_printer->Print("// char_data\n");
m_printer->Print("/* metadata char_data: */\n\"");
m_printer->Print(m_descriptor->full_name().c_str());
m_printer->Print("\\0\" /* = full message name */\n");
m_printer->Print("/* field char_data: */\n\"");
const int numFields = m_descriptor->field_count();
for (int i = 0; i < numFields; ++i) {
const FieldDescriptor *field = m_descriptor->field(i);
@ -175,17 +185,23 @@ void MessageDefinitionPrinter::printCharData()
m_printer->Print("\"\n\"");
m_printer->Print({ { "json_name", field->json_name() } }, "$json_name$\\0");
}
m_printer->Print("\"\n");
}
size_t MessageDefinitionPrinter::metaCharDataSize() const
{
return m_descriptor->full_name().size();
}
size_t MessageDefinitionPrinter::charDataSize() const
{
size_t size = 1; // 1 for the trailing null terminator
size_t size = 0;
const int numFields = m_descriptor->field_count();
for (int i = 0; i < numFields; ++i) {
const FieldDescriptor *field = m_descriptor->field(i);
size += field->json_name().length() + 1; // +1 for the embedded null terminator
}
return size;
return size + 1; // 1 for the trailing null terminator
}
void MessageDefinitionPrinter::printConstructors()

View File

@ -32,6 +32,7 @@ private:
void printFieldsOrdering();
void printUintData(const char *templateString);
void printCharData();
size_t metaCharDataSize() const;
size_t charDataSize() const;
void printConstructors();

View File

@ -571,6 +571,7 @@ const char *Templates::PropertyOrderingDataOpeningTemplate()
" $field_number_offset$, /* = field number offset */\n"
" $property_index_offset$, /* = property index offset */\n"
" $field_flags_offset$, /* = field flags offset */\n"
" $message_full_name_size$, /* = message full name length */\n"
" },\n";
}

View File

@ -43,6 +43,8 @@ void QtProtobufTypesGenerationTest::EmptyMessageTest()
{
QCOMPARE(qtprotobufnamespace::tests::EmptyMessage::propertyOrdering.fieldCount(), 0);
QCOMPARE(qtprotobufnamespace::tests::EmptyMessage::staticMetaObject.propertyCount(), 1);
QCOMPARE(qtprotobufnamespace::tests::EmptyMessage::propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.EmptyMessage");
}
void QtProtobufTypesGenerationTest::BoolMessageTest()
@ -56,6 +58,8 @@ void QtProtobufTypesGenerationTest::BoolMessageTest()
QCOMPARE(test.testFieldBool(), true);
QCOMPARE(SimpleBoolMessage::TestFieldBoolProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleBoolMessage");
}
void QtProtobufTypesGenerationTest::IntMessageTest()
@ -69,6 +73,8 @@ void QtProtobufTypesGenerationTest::IntMessageTest()
QCOMPARE(test.testFieldInt(), 1);
QCOMPARE(qtprotobufnamespace::tests::SimpleIntMessage::TestFieldIntProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleIntMessage");
}
void QtProtobufTypesGenerationTest::SIntMessageTest()
@ -82,6 +88,8 @@ void QtProtobufTypesGenerationTest::SIntMessageTest()
QCOMPARE(test.testFieldInt(), 1);
QCOMPARE(SimpleSIntMessage::TestFieldIntProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleSIntMessage");
}
void QtProtobufTypesGenerationTest::UIntMessageTest()
@ -95,6 +103,8 @@ void QtProtobufTypesGenerationTest::UIntMessageTest()
QCOMPARE(test.testFieldInt(), 1u);
QCOMPARE(SimpleUIntMessage::TestFieldIntProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleUIntMessage");
}
void QtProtobufTypesGenerationTest::Int64MessageTest()
@ -108,6 +118,8 @@ void QtProtobufTypesGenerationTest::Int64MessageTest()
QCOMPARE(test.testFieldInt(), 1);
QCOMPARE(SimpleInt64Message::TestFieldIntProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleInt64Message");
}
void QtProtobufTypesGenerationTest::SInt64MessageTest()
@ -121,6 +133,8 @@ void QtProtobufTypesGenerationTest::SInt64MessageTest()
QCOMPARE(test.testFieldInt(), 1);
QCOMPARE(SimpleSInt64Message::TestFieldIntProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleSInt64Message");
}
void QtProtobufTypesGenerationTest::UInt64MessageTest()
@ -134,6 +148,8 @@ void QtProtobufTypesGenerationTest::UInt64MessageTest()
QCOMPARE(test.testFieldInt(), 1u);
QCOMPARE(SimpleUInt64Message::TestFieldIntProtoFieldNumber, 1u);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleUInt64Message");
}
void QtProtobufTypesGenerationTest::FixedInt32MessageTest()
@ -147,6 +163,8 @@ void QtProtobufTypesGenerationTest::FixedInt32MessageTest()
QCOMPARE(test.testFieldFixedInt32(), 1u);
QCOMPARE(SimpleFixedInt32Message::TestFieldFixedInt32ProtoFieldNumber, 1u);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleFixedInt32Message");
}
void QtProtobufTypesGenerationTest::FixedInt64MessageTest()
@ -160,6 +178,8 @@ void QtProtobufTypesGenerationTest::FixedInt64MessageTest()
QCOMPARE(test.testFieldFixedInt64(), 1u);
QCOMPARE(SimpleFixedInt64Message::TestFieldFixedInt64ProtoFieldNumber, 1u);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleFixedInt64Message");
}
void QtProtobufTypesGenerationTest::SFixedInt32MessageTest()
@ -173,6 +193,8 @@ void QtProtobufTypesGenerationTest::SFixedInt32MessageTest()
QCOMPARE(test.testFieldFixedInt32(), 1);
QCOMPARE(SimpleSFixedInt32Message::TestFieldFixedInt32ProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleSFixedInt32Message");
}
void QtProtobufTypesGenerationTest::SFixedInt64MessageTest()
@ -186,6 +208,8 @@ void QtProtobufTypesGenerationTest::SFixedInt64MessageTest()
QCOMPARE(test.testFieldFixedInt64(), 1);
QCOMPARE(SimpleSFixedInt64Message::TestFieldFixedInt64ProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleSFixedInt64Message");
}
void QtProtobufTypesGenerationTest::StringMessageTest()
@ -201,6 +225,8 @@ void QtProtobufTypesGenerationTest::StringMessageTest()
QCOMPARE(test.testFieldString(), QStringLiteral("test1"));
QCOMPARE(SimpleStringMessage::TestFieldStringProtoFieldNumber, 6);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleStringMessage");
}
void QtProtobufTypesGenerationTest::FloatMessageTest()
@ -218,6 +244,8 @@ void QtProtobufTypesGenerationTest::FloatMessageTest()
QCOMPARE(test.testFieldFloat(), assignedValue);
QCOMPARE(SimpleFloatMessage::TestFieldFloatProtoFieldNumber, 7);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleFloatMessage");
}
void QtProtobufTypesGenerationTest::DoubleMessageTest()
@ -235,6 +263,8 @@ void QtProtobufTypesGenerationTest::DoubleMessageTest()
QCOMPARE(test.testFieldDouble(), assignedValue);
QCOMPARE(SimpleDoubleMessage::TestFieldDoubleProtoFieldNumber, 8);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleDoubleMessage");
}
void QtProtobufTypesGenerationTest::ComplexMessageTest()
@ -267,6 +297,8 @@ void QtProtobufTypesGenerationTest::BytesMessageTest()
QVERIFY(test.setProperty(propertyName, QVariant::fromValue<QByteArray>("\x01\x02\x03\x04\x05")));
QCOMPARE(test.property(propertyName).toByteArray(), QByteArray("\x01\x02\x03\x04\x05"));
QCOMPARE(test.testFieldBytes(), QByteArray("\x01\x02\x03\x04\x05"));
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.SimpleBytesMessage");
}
void QtProtobufTypesGenerationTest::AssignmentOperatorTest()

View File

@ -107,6 +107,11 @@ void QtProtobufNestedTest::SimpleTest()
.value<NestedFieldMessage2::NestedMessageLevel1::NestedMessageLevel2 *>()),
level2);
QCOMPARE(test2.nested2(), level2);
QCOMPARE(test.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.nested.NestedFieldMessage");
QCOMPARE(nestedMsg.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.nested.NestedFieldMessage.NestedMessage");
}
void QtProtobufNestedTest::SerializationTest()
@ -217,6 +222,10 @@ void QtProtobufNestedTest::NeighborTest()
.value<NestedFieldMessage2::NestedMessageLevel1::NestedMessageLevel2 *>()),
level2);
QCOMPARE(test.neighborNested2(), level2);
QCOMPARE(level2.propertyOrdering.getMessageFullName(),
"qtprotobufnamespace.tests.nested.NestedFieldMessage2.NestedMessageLevel1."
"NestedMessageLevel2");
}
void QtProtobufNestedTest::NestedNoFieldsTest()

View File

@ -39,6 +39,7 @@ void QtProtobufNoPackageTypesGenerationTest::NoPackageSimpleIntMessageTest()
QCOMPARE(test.testFieldInt(), 1);
QCOMPARE(::SimpleIntMessage::TestFieldIntProtoFieldNumber, 1);
QCOMPARE(test.propertyOrdering.getMessageFullName(), "SimpleIntMessage");
}
void QtProtobufNoPackageTypesGenerationTest::NoPackageEnumTest()
@ -79,6 +80,7 @@ void QtProtobufNoPackageTypesGenerationTest::NoPackageExternalTest()
QVariant::fromValue<SimpleIntMessageExt *>(new SimpleIntMessageExt(intMsg))));
QCOMPARE(test.property(propertyName).value<SimpleIntMessageExt*>()->testFieldInt(), 42);
QCOMPARE(test.testField().testFieldInt(), 42);
QCOMPARE(test.propertyOrdering.getMessageFullName(), "NoPackageExternalMessage");
}
void QtProtobufNoPackageTypesGenerationTest::NoPackageMessageTest()
@ -94,6 +96,7 @@ void QtProtobufNoPackageTypesGenerationTest::NoPackageMessageTest()
propertyName, QVariant::fromValue<SimpleIntMessage *>(new SimpleIntMessage(intMsg))));
QCOMPARE(test.property(propertyName).value<SimpleIntMessage*>()->testFieldInt(), 42);
QCOMPARE(test.testField().testFieldInt(), 42);
QCOMPARE(test.propertyOrdering.getMessageFullName(), "NoPackageMessage");
}
QTEST_MAIN(QtProtobufNoPackageTypesGenerationTest)