diff --git a/src/protobuf/qtprotobuftypes.cpp b/src/protobuf/qtprotobuftypes.cpp index 3e4fb5c1..91695486 100644 --- a/src/protobuf/qtprotobuftypes.cpp +++ b/src/protobuf/qtprotobuftypes.cpp @@ -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); diff --git a/src/protobuf/qtprotobuftypes.h b/src/protobuf/qtprotobuftypes.h index 91fceb97..d4a5720c 100644 --- a/src/protobuf/qtprotobuftypes.h +++ b/src/protobuf/qtprotobuftypes.h @@ -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; diff --git a/src/tools/qtprotobufgen/messagedefinitionprinter.cpp b/src/tools/qtprotobufgen/messagedefinitionprinter.cpp index 25bcf637..5b47bb7c 100644 --- a/src/tools/qtprotobufgen/messagedefinitionprinter.cpp +++ b/src/tools/qtprotobufgen/messagedefinitionprinter.cpp @@ -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 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() diff --git a/src/tools/qtprotobufgen/messagedefinitionprinter.h b/src/tools/qtprotobufgen/messagedefinitionprinter.h index 96f5a186..adf31097 100644 --- a/src/tools/qtprotobufgen/messagedefinitionprinter.h +++ b/src/tools/qtprotobufgen/messagedefinitionprinter.h @@ -32,6 +32,7 @@ private: void printFieldsOrdering(); void printUintData(const char *templateString); void printCharData(); + size_t metaCharDataSize() const; size_t charDataSize() const; void printConstructors(); diff --git a/src/tools/qtprotobufgen/templates.cpp b/src/tools/qtprotobufgen/templates.cpp index 0f82b284..7a0bfa11 100644 --- a/src/tools/qtprotobufgen/templates.cpp +++ b/src/tools/qtprotobufgen/templates.cpp @@ -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"; } diff --git a/tests/auto/protobuf/basic/tst_protobuf_basictypes.cpp b/tests/auto/protobuf/basic/tst_protobuf_basictypes.cpp index 39a887ad..644d412e 100644 --- a/tests/auto/protobuf/basic/tst_protobuf_basictypes.cpp +++ b/tests/auto/protobuf/basic/tst_protobuf_basictypes.cpp @@ -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("\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() diff --git a/tests/auto/protobuf/nested/tst_protobuf_nestedtypes.cpp b/tests/auto/protobuf/nested/tst_protobuf_nestedtypes.cpp index d6edbdc1..ba7f7803 100644 --- a/tests/auto/protobuf/nested/tst_protobuf_nestedtypes.cpp +++ b/tests/auto/protobuf/nested/tst_protobuf_nestedtypes.cpp @@ -107,6 +107,11 @@ void QtProtobufNestedTest::SimpleTest() .value()), 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()), level2); QCOMPARE(test.neighborNested2(), level2); + + QCOMPARE(level2.propertyOrdering.getMessageFullName(), + "qtprotobufnamespace.tests.nested.NestedFieldMessage2.NestedMessageLevel1." + "NestedMessageLevel2"); } void QtProtobufNestedTest::NestedNoFieldsTest() diff --git a/tests/auto/protobuf/nopackage/tst_protobuf_nopackagetypes.cpp b/tests/auto/protobuf/nopackage/tst_protobuf_nopackagetypes.cpp index 0a3c59a9..471762a7 100644 --- a/tests/auto/protobuf/nopackage/tst_protobuf_nopackagetypes.cpp +++ b/tests/auto/protobuf/nopackage/tst_protobuf_nopackagetypes.cpp @@ -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(new SimpleIntMessageExt(intMsg)))); QCOMPARE(test.property(propertyName).value()->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(new SimpleIntMessage(intMsg)))); QCOMPARE(test.property(propertyName).value()->testFieldInt(), 42); QCOMPARE(test.testField().testFieldInt(), 42); + QCOMPARE(test.propertyOrdering.getMessageFullName(), "NoPackageMessage"); } QTEST_MAIN(QtProtobufNoPackageTypesGenerationTest)