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 &ltrim(std::string &s);