Submitted By: Pierre Labastie (pierre dot labastie at neuf dot fr) Date: 2025-03-19 Initial Package Version: 6.8.2 Upstream Status: Applied Origin: Upstream Description: Fix building against protobuf-30 and higher From 891b739d4979f532019fe485153549128aa5a7b8 Mon Sep 17 00:00:00 2001 From: Alexey Edelev <alexey.edelev@qt.io> Date: Tue, 18 Mar 2025 14:51:13 +0100 Subject: [PATCH 1/1] Adapt the generator code to be compatible with protobuf >= 30 The newer protobuf version uses string_views as the return value. Wrap the respecitive API with constructing std::string and update some of the util functions to accept std::string_view arguments but not plain std::string. Fixes: QTBUG-134885 Pick-to: 6.8 6.9 Change-Id: I8bc06c46167a8b1bc0dca36242249e672ffcccd3 --- .../qtprotobufgen/messagedefinitionprinter.cpp | 12 +++--- src/tools/qtprotobufgen/qprotobufgenerator.cpp | 7 ++-- src/tools/qtprotoccommon/generatorbase.cpp | 12 +++--- src/tools/qtprotoccommon/generatorcommon.cpp | 47 +++++++++++----------- src/tools/qtprotoccommon/generatorcommon.h | 12 +++--- src/tools/qtprotoccommon/utils.cpp | 40 +++++++++--------- src/tools/qtprotoccommon/utils.h | 8 ++-- 7 files changed, 73 insertions(+), 65 deletions(-) diff -Naur a/qtgrpc/src/tools/qtprotobufgen/messagedefinitionprinter.cpp b/qtgrpc/src/tools/qtprotobufgen/messagedefinitionprinter.cpp --- a/qtgrpc/src/tools/qtprotobufgen/messagedefinitionprinter.cpp 2025-01-24 10:12:01.000000000 +0100 +++ b/qtgrpc/src/tools/qtprotobufgen/messagedefinitionprinter.cpp 2025-03-19 08:22:48.240976678 +0100 @@ -245,11 +245,11 @@ for (int i = 0, propertyIndex = 0; i < numFields; ++i, ++propertyIndex) { const FieldDescriptor *field = m_descriptor->field(i); const std::map<std::string, std::string> variables = { - { "json_name_offset", std::to_string(jsonOffset) }, - { "field_number", std::to_string(field->number()) }, - { "property_index", std::to_string(propertyIndex) }, - { "field_flags", common::collectFieldFlags(field) }, - { "json_name", field->json_name() }, + { "json_name_offset", std::to_string(jsonOffset) }, + { "field_number", std::to_string(field->number()) }, + { "property_index", std::to_string(propertyIndex) }, + { "field_flags", common::collectFieldFlags(field) }, + { "json_name", std::string{ field->json_name() } }, }; // Oneof and optional properties generate additional has<FieldName> property next to the @@ -270,7 +270,7 @@ 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(std::string{m_descriptor->full_name()}.c_str()); m_printer->Print("\\0\" /* = full message name */\n"); m_printer->Print("/* field char_data: */\n\""); diff -Naur a/qtgrpc/src/tools/qtprotobufgen/qprotobufgenerator.cpp b/qtgrpc/src/tools/qtprotobufgen/qprotobufgenerator.cpp --- a/qtgrpc/src/tools/qtprotobufgen/qprotobufgenerator.cpp 2025-01-24 10:12:01.000000000 +0100 +++ b/qtgrpc/src/tools/qtprotobufgen/qprotobufgenerator.cpp 2025-03-19 08:22:48.241109708 +0100 @@ -167,9 +167,10 @@ const auto *field = message->field(i); if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated() && common::isQtType(field)) { - externalIncludes.insert(field->message_type()->file()->package() - + "/" + field->message_type()->name()); - qtTypesSet.insert(field->message_type()->file()->package()); + const std::string package{ field->message_type()->file()->package() }; + externalIncludes.insert(package + "/" + + std::string{ field->message_type()->name() }); + qtTypesSet.insert(package); } if (common::isOptionalField(field)) diff -Naur a/qtgrpc/src/tools/qtprotoccommon/generatorbase.cpp b/qtgrpc/src/tools/qtprotoccommon/generatorbase.cpp --- a/qtgrpc/src/tools/qtprotoccommon/generatorbase.cpp 2025-01-24 10:12:01.000000000 +0100 +++ b/qtgrpc/src/tools/qtprotoccommon/generatorbase.cpp 2025-03-19 08:22:48.241216719 +0100 @@ -48,7 +48,7 @@ std::set<std::string> extraNamespaceFiles; for (const FileDescriptor *file : files) { assert(file != nullptr); - extraNamespaceFiles.insert(file->name()); + extraNamespaceFiles.insert(std::string{ file->name() }); } common::setExtraNamespacedFiles(extraNamespaceFiles); } @@ -68,8 +68,9 @@ assert(file != nullptr); const bool hasQtNamespace = (Options::instance().extraNamespace() == "QT_NAMESPACE"); - const std::string scopeNamespaces - = common::getFullNamespace(file->package() + ".noop", "::", true); + const std::string scopeNamespaces = common::getFullNamespace(std::string{ file->package() } + + ".noop", + "::", true); printer->Print("\n"); if (hasQtNamespace || file->package() == "QtCore" || file->package() == "QtGui") @@ -87,8 +88,9 @@ assert(printer != nullptr); const bool hasQtNamespace = (Options::instance().extraNamespace() == "QT_NAMESPACE"); - const std::string scopeNamespaces - = common::getFullNamespace(file->package() + ".noop", "::", true); + const std::string scopeNamespaces = common::getFullNamespace(std::string{ file->package() } + + ".noop", + "::", true); if (!scopeNamespaces.empty()) { printer->Print({ { "scope_namespaces", scopeNamespaces } }, CommonTemplates::NamespaceClosingTemplate()); diff -Naur a/qtgrpc/src/tools/qtprotoccommon/generatorcommon.cpp b/qtgrpc/src/tools/qtprotoccommon/generatorcommon.cpp --- a/qtgrpc/src/tools/qtprotoccommon/generatorcommon.cpp 2025-01-24 10:12:01.000000000 +0100 +++ b/qtgrpc/src/tools/qtprotoccommon/generatorcommon.cpp 2025-03-19 08:22:48.241317508 +0100 @@ -97,7 +97,7 @@ std::string common::getNestedNamespace(const Descriptor *type, std::string_view separator) { assert(type != nullptr); - std::string namespaces = type->file()->package(); + std::string namespaces{ type->file()->package() }; std::string nestingNamespaces; const Descriptor *containingType = type->containing_type(); @@ -150,7 +150,7 @@ std::string scopeNamespaces = getScopeNamespace(type, scope); std::string qmlPackage = getFullNamespace(type, "."); - std::string name = type->name(); + std::string name{ type->name() }; std::string fullName = name; std::string scopeName = name; @@ -175,7 +175,7 @@ std::string namespaces = getFullNamespace(type, "::"); std::string qmlPackage = getFullNamespace(type, "."); - std::string name = type->name(); + std::string name{ type->name() }; std::string listName; if (type->full_name() == "google.protobuf.Any") { namespaces = "QtProtobuf"; @@ -339,10 +339,10 @@ MethodMap common::produceMethodMap(const MethodDescriptor *method, const std::string &scope) { - std::string inputTypeName = method->input_type()->full_name(); - std::string outputTypeName = method->output_type()->full_name(); - std::string methodName = method->name(); - std::string methodNameUpper = method->name(); + std::string inputTypeName{ method->input_type()->full_name() }; + std::string outputTypeName{ method->output_type()->full_name() }; + std::string methodName{ method->name() }; + std::string methodNameUpper{ method->name() }; methodNameUpper[0] = static_cast<char>(utils::toAsciiUpper(methodNameUpper[0])); inputTypeName = utils::replace(inputTypeName, ".", "::"); outputTypeName = utils::replace(outputTypeName, ".", "::"); @@ -350,7 +350,7 @@ std::string senderName = methodNameUpper; senderName += "Sender"; - std::string serviceName = method->service()->name(); + std::string serviceName{ method->service()->name() }; //Make sure that we don't clash the same stream names from different services std::string senderQmlName = serviceName; @@ -388,9 +388,9 @@ TypeMap common::produceServiceTypeMap(const ServiceDescriptor *service, const Descriptor *scope) { - const std::string name = "Service"; - const std::string fullName = "Service"; - const std::string scopeName = service->name(); + const std::string name{ "Service" }; + const std::string fullName{ "Service" }; + const std::string scopeName{ service->name() }; static const std::string exportMacro = common::buildExportMacro(); const std::string namespaces = getFullNamespace(service, "::"); @@ -408,16 +408,16 @@ TypeMap common::produceClientTypeMap(const ServiceDescriptor *service, const Descriptor *scope) { - const std::string name = "Client"; - const std::string fullName = "Client"; - const std::string scopeName = service->name(); + const std::string name{ "Client" }; + const std::string fullName{ "Client" }; + const std::string scopeName{ service->name() }; static const std::string exportMacro = common::buildExportMacro(); const std::string namespaces = getFullNamespace(service, "::"); const std::string scopeNamespaces = getScopeNamespace(namespaces, getFullNamespace(scope, "::")); - const std::string serviceName = service->full_name(); + const std::string serviceName{ service->full_name() }; return { { "classname", name }, { "classname_low_case", utils::deCapitalizeAsciiName(name) }, { "full_type", fullName }, @@ -430,9 +430,9 @@ TypeMap common::produceQmlClientTypeMap(const ServiceDescriptor *service, const Descriptor *scope) { - const std::string name = "QmlClient"; - const std::string fullName = "QmlClient"; - const std::string serviceName = service->name(); + const std::string name{ "QmlClient" }; + const std::string fullName{ "QmlClient" }; + const std::string serviceName{ service->name() }; static const std::string exportMacro = common::buildExportMacro(); const std::string namespaces = getFullNamespace(service, "::"); @@ -596,12 +596,13 @@ return propertyMap; } -std::string common::qualifiedCppName(const std::string &name) +std::string common::qualifiedCppName(std::string_view name) { - return utils::contains(CommonTemplates::ListOfCppExceptions(), name) ? name + "_" : name; + return utils::contains(CommonTemplates::ListOfCppExceptions(), name) ? std::string{ name } + "_" + : std::string{ name }; } -std::string common::qualifiedQmlName(const std::string &name) +std::string common::qualifiedQmlName(std::string_view name) { std::string fieldName(name); const std::vector<std::string> &searchExceptions = CommonTemplates::ListOfQmlExceptions(); @@ -798,9 +799,9 @@ return flags; } -bool common::isExtraNamespacedFile(const std::string &file) +bool common::isExtraNamespacedFile(std::string_view file) { - return m_extraNamespacedFiles.find(file) != m_extraNamespacedFiles.end(); + return m_extraNamespacedFiles.find(std::string{ file }) != m_extraNamespacedFiles.end(); } void common::setExtraNamespacedFiles(const std::set<std::string> &files) diff -Naur a/qtgrpc/src/tools/qtprotoccommon/generatorcommon.h b/qtgrpc/src/tools/qtprotoccommon/generatorcommon.h --- a/qtgrpc/src/tools/qtprotoccommon/generatorcommon.h 2025-01-24 10:12:01.000000000 +0100 +++ b/qtgrpc/src/tools/qtprotoccommon/generatorcommon.h 2025-03-19 08:22:48.241505320 +0100 @@ -64,9 +64,9 @@ } } - return getFullNamespace(type->file()->package() + nestingNamespaces + '.' + type->name(), - separator, - common::isExtraNamespacedFile(std::string(type->file()->name()))); + return getFullNamespace(std::string{ type->file()->package() } + nestingNamespaces + '.' + + std::string{ type->name() }, + separator, common::isExtraNamespacedFile(type->file()->name())); } template<typename T> @@ -123,8 +123,8 @@ static TypeMap produceClientTypeMap(const ServiceDescriptor *service, const Descriptor *scope); static TypeMap produceQmlClientTypeMap(const ServiceDescriptor *service, const Descriptor *scope); - static std::string qualifiedCppName(const std::string &name); - static std::string qualifiedQmlName(const std::string &name); + static std::string qualifiedCppName(std::string_view name); + static std::string qualifiedQmlName(std::string_view name); static bool isOneofField(const FieldDescriptor *field); static bool isOptionalField(const FieldDescriptor *field); static bool isTriviallyCopyable(const FieldDescriptor *field); @@ -155,7 +155,7 @@ static std::string collectFieldFlags(const google::protobuf::FieldDescriptor *field); - static bool isExtraNamespacedFile(const std::string &file); + static bool isExtraNamespacedFile(std::string_view file); static void setExtraNamespacedFiles(const std::set<std::string> &files); static std::string headerGuardFromFilename(std::string fileName); diff -Naur a/qtgrpc/src/tools/qtprotoccommon/utils.cpp b/qtgrpc/src/tools/qtprotoccommon/utils.cpp --- a/qtgrpc/src/tools/qtprotoccommon/utils.cpp 2025-01-24 10:12:01.000000000 +0100 +++ b/qtgrpc/src/tools/qtprotoccommon/utils.cpp 2025-03-19 08:22:48.241592092 +0100 @@ -78,20 +78,22 @@ std::transform(std::begin(str), std::end(str), std::begin(str), utils::toAsciiUpper); } -std::string removeFileSuffix(std::string fileName) +std::string removeFileSuffix(std::string_view fileName) { - size_t dot = fileName.rfind('.'), slash = fileName.rfind('/'); + std::string result(fileName); + size_t dot = result.rfind('.'), slash = result.rfind('/'); if (dot != std::string::npos && (slash == std::string::npos || dot > slash)) - fileName.resize(dot); - return fileName; + result.resize(dot); + return result; } -std::string extractFileBasename(std::string fileName) +std::string extractFileBasename(std::string_view fileName) { - size_t dot = fileName.rfind('.'), slash = fileName.rfind('/'); + std::string result(fileName); + size_t dot = result.rfind('.'), slash = result.rfind('/'); if (dot != std::string::npos && (slash == std::string::npos || dot > slash)) - fileName.resize(dot); - return slash != std::string::npos ? fileName.substr(slash + 1) : fileName; + result.resize(dot); + return slash != std::string::npos ? result.substr(slash + 1) : result; } std::string toValidIdentifier(std::string_view name) @@ -113,20 +115,22 @@ return out; } -std::string capitalizeAsciiName(std::string name) +std::string capitalizeAsciiName(std::string_view name) { - if (name.empty() || !isAsciiAlpha(name[0])) - return name; - name[0] &= ~char(0x20); - return name; + std::string result(name); + if (result.empty() || !isAsciiAlpha(result[0])) + return result; + result[0] &= ~char(0x20); + return result; } -std::string deCapitalizeAsciiName(std::string name) +std::string deCapitalizeAsciiName(std::string_view name) { - if (name.empty() || !isAsciiAlpha(name[0])) - return name; - name[0] |= char(0x20); - return name; + std::string result(name); + if (result.empty() || !isAsciiAlpha(result[0])) + return result; + result[0] |= char(0x20); + return result; } std::string &rtrim(std::string &s) diff -Naur a/qtgrpc/src/tools/qtprotoccommon/utils.h b/qtgrpc/src/tools/qtprotoccommon/utils.h --- a/qtgrpc/src/tools/qtprotoccommon/utils.h 2025-01-24 10:12:01.000000000 +0100 +++ b/qtgrpc/src/tools/qtprotoccommon/utils.h 2025-03-19 08:22:48.241658707 +0100 @@ -27,11 +27,11 @@ std::string replace(std::string_view where, std::string_view from, std::string_view to); void asciiToLower(std::string &str); void asciiToUpper(std::string &str); -std::string removeFileSuffix(std::string fileName); -std::string extractFileBasename(std::string fileName); +std::string removeFileSuffix(std::string_view fileName); +std::string extractFileBasename(std::string_view fileName); std::string toValidIdentifier(std::string_view name); -std::string capitalizeAsciiName(std::string name); -std::string deCapitalizeAsciiName(std::string name); +std::string capitalizeAsciiName(std::string_view name); +std::string deCapitalizeAsciiName(std::string_view name); std::string &rtrim(std::string &s); // trim from beginning of string (left) std::string <rim(std::string &s);