summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/protobuf/protobuf-c/protobuf-30.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-devtools/protobuf/protobuf-c/protobuf-30.patch')
-rw-r--r--meta-oe/recipes-devtools/protobuf/protobuf-c/protobuf-30.patch1446
1 files changed, 1446 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/protobuf/protobuf-c/protobuf-30.patch b/meta-oe/recipes-devtools/protobuf/protobuf-c/protobuf-30.patch
new file mode 100644
index 0000000000..1aae1f17b0
--- /dev/null
+++ b/meta-oe/recipes-devtools/protobuf/protobuf-c/protobuf-30.patch
@@ -0,0 +1,1446 @@
1From b28683f8027bf1e886b748b5603eb16d203b5a92 Mon Sep 17 00:00:00 2001
2From: Robert Edmonds <edmonds@users.noreply.github.com>
3Date: Sat, 8 Feb 2025 18:18:33 -0500
4Subject: [PATCH 01/11] protoc-gen-c/c_helpers.h: Move compat defines into new
5 header file compat.h
6
7Upstream-Status: Backport [https://gitlab.archlinux.org/archlinux/packaging/packages/protobuf-c/-/blob/main/protobuf-30.patch]
8Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
9
10---
11 protoc-gen-c/c_field.cc | 1 +
12 protoc-gen-c/c_helpers.cc | 1 +
13 protoc-gen-c/c_helpers.h | 10 -------
14 protoc-gen-c/c_message.cc | 1 +
15 protoc-gen-c/c_primitive_field.cc | 1 +
16 protoc-gen-c/compat.h | 46 +++++++++++++++++++++++++++++++
17 protoc-gen-c/main.cc | 1 +
18 7 files changed, 51 insertions(+), 10 deletions(-)
19 create mode 100644 protoc-gen-c/compat.h
20
21diff --git a/protoc-gen-c/c_field.cc b/protoc-gen-c/c_field.cc
22index 5e79967b..d6d8597e 100644
23--- a/protoc-gen-c/c_field.cc
24+++ b/protoc-gen-c/c_field.cc
25@@ -74,6 +74,7 @@
26 #include "c_message_field.h"
27 #include "c_primitive_field.h"
28 #include "c_string_field.h"
29+#include "compat.h"
30
31 namespace protobuf_c {
32
33diff --git a/protoc-gen-c/c_helpers.cc b/protoc-gen-c/c_helpers.cc
34index 5edcf904..c38843f8 100644
35--- a/protoc-gen-c/c_helpers.cc
36+++ b/protoc-gen-c/c_helpers.cc
37@@ -73,6 +73,7 @@
38 #include <google/protobuf/stubs/common.h>
39
40 #include "c_helpers.h"
41+#include "compat.h"
42
43 namespace protobuf_c {
44
45diff --git a/protoc-gen-c/c_helpers.h b/protoc-gen-c/c_helpers.h
46index 943676e9..e69504bb 100644
47--- a/protoc-gen-c/c_helpers.h
48+++ b/protoc-gen-c/c_helpers.h
49@@ -186,16 +186,6 @@ inline int FieldSyntax(const google::protobuf::FieldDescriptor* field) {
50 return 2;
51 }
52
53-// Work around changes in protobuf >= 22.x without breaking compilation against
54-// older protobuf versions.
55-#if GOOGLE_PROTOBUF_VERSION >= 4022000
56-# define GOOGLE_ARRAYSIZE ABSL_ARRAYSIZE
57-# define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
58-# define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
59-# define GOOGLE_DCHECK_GE ABSL_DCHECK_GE
60-# define GOOGLE_LOG ABSL_LOG
61-#endif
62-
63 } // namespace protobuf_c
64
65 #endif // PROTOBUF_C_PROTOC_GEN_C_C_HELPERS_H__
66diff --git a/protoc-gen-c/c_message.cc b/protoc-gen-c/c_message.cc
67index d4a9a01e..46413873 100644
68--- a/protoc-gen-c/c_message.cc
69+++ b/protoc-gen-c/c_message.cc
70@@ -78,6 +78,7 @@
71 #include "c_extension.h"
72 #include "c_helpers.h"
73 #include "c_message.h"
74+#include "compat.h"
75
76 namespace protobuf_c {
77
78diff --git a/protoc-gen-c/c_primitive_field.cc b/protoc-gen-c/c_primitive_field.cc
79index 253b00bd..588f60e6 100644
80--- a/protoc-gen-c/c_primitive_field.cc
81+++ b/protoc-gen-c/c_primitive_field.cc
82@@ -67,6 +67,7 @@
83
84 #include "c_helpers.h"
85 #include "c_primitive_field.h"
86+#include "compat.h"
87
88 namespace protobuf_c {
89
90diff --git a/protoc-gen-c/compat.h b/protoc-gen-c/compat.h
91new file mode 100644
92index 00000000..2ee78281
93--- /dev/null
94+++ b/protoc-gen-c/compat.h
95@@ -0,0 +1,46 @@
96+// Copyright (c) 2008-2025, Dave Benson and the protobuf-c authors.
97+// All rights reserved.
98+//
99+// Redistribution and use in source and binary forms, with or without
100+// modification, are permitted provided that the following conditions are
101+// met:
102+//
103+// * Redistributions of source code must retain the above copyright
104+// notice, this list of conditions and the following disclaimer.
105+//
106+// * Redistributions in binary form must reproduce the above
107+// copyright notice, this list of conditions and the following disclaimer
108+// in the documentation and/or other materials provided with the
109+// distribution.
110+//
111+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
112+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
113+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
114+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
115+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
116+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
117+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
118+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
119+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
120+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
121+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
122+
123+#ifndef PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
124+#define PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
125+
126+#if GOOGLE_PROTOBUF_VERSION >= 4022000
127+# define GOOGLE_ARRAYSIZE ABSL_ARRAYSIZE
128+# define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
129+# define GOOGLE_DCHECK_GE ABSL_DCHECK_GE
130+# define GOOGLE_LOG ABSL_LOG
131+#endif
132+
133+namespace protobuf_c {
134+
135+namespace compat {
136+
137+} // namespace compat
138+
139+} // namespace protobuf_c
140+
141+#endif // PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
142diff --git a/protoc-gen-c/main.cc b/protoc-gen-c/main.cc
143index 0656c113..5ab929d3 100644
144--- a/protoc-gen-c/main.cc
145+++ b/protoc-gen-c/main.cc
146@@ -32,6 +32,7 @@
147
148 #include "c_generator.h"
149 #include "c_helpers.h"
150+#include "compat.h"
151
152 int main(int argc, char* argv[]) {
153 protobuf_c::CGenerator c_generator;
154
155From 1678f1fba6f2d3e5c1db2817495ddcd72bd4e87b Mon Sep 17 00:00:00 2001
156From: Robert Edmonds <edmonds@users.noreply.github.com>
157Date: Sat, 8 Feb 2025 20:09:03 -0500
158Subject: [PATCH 02/11] protoc-gen-c/compat.h: Add `compat::StringView` type
159
160protobuf >= 30.x replaces `const std::string&` in various APIs with
161its own string view type that may actually be a `absl::string_view`.
162Introduce our own `compat::StringView` type that we can use instead
163of `const std::string&` in order to support compiling across multiple
164protobuf versions.
165---
166 protoc-gen-c/compat.h | 8 ++++++++
167 1 file changed, 8 insertions(+)
168
169diff --git a/protoc-gen-c/compat.h b/protoc-gen-c/compat.h
170index 2ee78281..fe8041b5 100644
171--- a/protoc-gen-c/compat.h
172+++ b/protoc-gen-c/compat.h
173@@ -28,6 +28,8 @@
174 #ifndef PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
175 #define PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
176
177+#include <string>
178+
179 #if GOOGLE_PROTOBUF_VERSION >= 4022000
180 # define GOOGLE_ARRAYSIZE ABSL_ARRAYSIZE
181 # define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
182@@ -39,6 +41,12 @@ namespace protobuf_c {
183
184 namespace compat {
185
186+#if GOOGLE_PROTOBUF_VERSION >= 6030000
187+typedef google::protobuf::internal::DescriptorStringView StringView;
188+#else
189+typedef const std::string& StringView;
190+#endif
191+
192 } // namespace compat
193
194 } // namespace protobuf_c
195
196From db5252c131c82fb48ee599179b6989a577b7fbc8 Mon Sep 17 00:00:00 2001
197From: Robert Edmonds <edmonds@users.noreply.github.com>
198Date: Sat, 8 Feb 2025 20:13:44 -0500
199Subject: [PATCH 03/11] Remove some unused functions
200
201---
202 protoc-gen-c/c_helpers.cc | 64 ---------------------------------------
203 protoc-gen-c/c_helpers.h | 3 --
204 2 files changed, 67 deletions(-)
205
206diff --git a/protoc-gen-c/c_helpers.cc b/protoc-gen-c/c_helpers.cc
207index c38843f8..bbb4a615 100644
208--- a/protoc-gen-c/c_helpers.cc
209+++ b/protoc-gen-c/c_helpers.cc
210@@ -90,14 +90,6 @@ namespace protobuf_c {
211 #pragma warning(disable:4996)
212 #endif
213
214-std::string DotsToUnderscores(const std::string& name) {
215- return StringReplace(name, ".", "_", true);
216-}
217-
218-std::string DotsToColons(const std::string& name) {
219- return StringReplace(name, ".", "::", true);
220-}
221-
222 std::string SimpleFtoa(float f) {
223 char buf[100];
224 snprintf(buf,sizeof(buf),"%.*g", FLT_DIG, f);
225@@ -333,11 +325,6 @@ std::string FilenameIdentifier(const std::string& filename) {
226 return result;
227 }
228
229-// Return the name of the BuildDescriptors() function for a given file.
230-std::string GlobalBuildDescriptorsName(const std::string& filename) {
231- return "proto_BuildDescriptors_" + FilenameIdentifier(filename);
232-}
233-
234 std::string GetLabelName(google::protobuf::FieldDescriptor::Label label) {
235 switch (label) {
236 case google::protobuf::FieldDescriptor::LABEL_OPTIONAL: return "optional";
237@@ -392,57 +379,6 @@ WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *
238 }
239 }
240
241-
242-
243-// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx
244-// XXXXXXXXX this stuff is copied from strutils.cc !!!! XXXXXXXXXXXXXXXXXXXXXXXXXXXXx
245-// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx
246-// ----------------------------------------------------------------------
247-// StringReplace()
248-// Replace the "old" pattern with the "new" pattern in a string,
249-// and append the result to "res". If replace_all is false,
250-// it only replaces the first instance of "old."
251-// ----------------------------------------------------------------------
252-
253-void StringReplace(const std::string& s, const std::string& oldsub,
254- const std::string& newsub, bool replace_all,
255- std::string* res) {
256- if (oldsub.empty()) {
257- res->append(s); // if empty, append the given string.
258- return;
259- }
260-
261- std::string::size_type start_pos = 0;
262- std::string::size_type pos;
263- do {
264- pos = s.find(oldsub, start_pos);
265- if (pos == std::string::npos) {
266- break;
267- }
268- res->append(s, start_pos, pos - start_pos);
269- res->append(newsub);
270- start_pos = pos + oldsub.size(); // start searching again after the "old"
271- } while (replace_all);
272- res->append(s, start_pos, s.length() - start_pos);
273-}
274-
275-
276-// ----------------------------------------------------------------------
277-// StringReplace()
278-// Give me a string and two patterns "old" and "new", and I replace
279-// the first instance of "old" in the string with "new", if it
280-// exists. If "global" is true; call this repeatedly until it
281-// fails. RETURN a new string, regardless of whether the replacement
282-// happened or not.
283-// ----------------------------------------------------------------------
284-
285-std::string StringReplace(const std::string& s, const std::string& oldsub,
286- const std::string& newsub, bool replace_all) {
287- std::string ret;
288- StringReplace(s, oldsub, newsub, replace_all, &ret);
289- return ret;
290-}
291-
292 // ----------------------------------------------------------------------
293 // SplitStringUsing()
294 // Split a string using a character delimiter. Append the components
295diff --git a/protoc-gen-c/c_helpers.h b/protoc-gen-c/c_helpers.h
296index e69504bb..377d4272 100644
297--- a/protoc-gen-c/c_helpers.h
298+++ b/protoc-gen-c/c_helpers.h
299@@ -150,9 +150,6 @@ const char* DeclaredTypeMethodName(google::protobuf::FieldDescriptor::Type type)
300 // Convert a file name into a valid identifier.
301 std::string FilenameIdentifier(const std::string& filename);
302
303-// Return the name of the BuildDescriptors() function for a given file.
304-std::string GlobalBuildDescriptorsName(const std::string& filename);
305-
306 // return 'required', 'optional', or 'repeated'
307 std::string GetLabelName(google::protobuf::FieldDescriptor::Label label);
308
309
310From bc2cb66d908f016dd3f7082c8a6ad7c58bc03412 Mon Sep 17 00:00:00 2001
311From: Robert Edmonds <edmonds@users.noreply.github.com>
312Date: Sat, 8 Feb 2025 20:18:05 -0500
313Subject: [PATCH 04/11] Use `compat::StringView` type across various function
314 signatures
315
316---
317 protoc-gen-c/c_helpers.cc | 44 +++++++++++++++++++++------------------
318 protoc-gen-c/c_helpers.h | 36 ++++++++++++++++----------------
319 2 files changed, 42 insertions(+), 38 deletions(-)
320
321diff --git a/protoc-gen-c/c_helpers.cc b/protoc-gen-c/c_helpers.cc
322index bbb4a615..c759c8c2 100644
323--- a/protoc-gen-c/c_helpers.cc
324+++ b/protoc-gen-c/c_helpers.cc
325@@ -96,6 +96,7 @@ std::string SimpleFtoa(float f) {
326 buf[sizeof(buf)-1] = 0; /* should NOT be necessary */
327 return buf;
328 }
329+
330 std::string SimpleDtoa(double d) {
331 char buf[100];
332 snprintf(buf,sizeof(buf),"%.*g", DBL_DIG, d);
333@@ -103,7 +104,7 @@ std::string SimpleDtoa(double d) {
334 return buf;
335 }
336
337-std::string CamelToUpper(const std::string &name) {
338+std::string CamelToUpper(compat::StringView name) {
339 bool was_upper = true; // suppress initial _
340 std::string rv = "";
341 int len = name.length();
342@@ -120,7 +121,8 @@ std::string CamelToUpper(const std::string &name) {
343 }
344 return rv;
345 }
346-std::string CamelToLower(const std::string &name) {
347+
348+std::string CamelToLower(compat::StringView name) {
349 bool was_upper = true; // suppress initial _
350 std::string rv = "";
351 int len = name.length();
352@@ -138,8 +140,7 @@ std::string CamelToLower(const std::string &name) {
353 return rv;
354 }
355
356-
357-std::string ToUpper(const std::string &name) {
358+std::string ToUpper(compat::StringView name) {
359 std::string rv = "";
360 int len = name.length();
361 for (int i = 0; i < len; i++) {
362@@ -147,7 +148,8 @@ std::string ToUpper(const std::string &name) {
363 }
364 return rv;
365 }
366-std::string ToLower(const std::string &name) {
367+
368+std::string ToLower(compat::StringView name) {
369 std::string rv = "";
370 int len = name.length();
371 for (int i = 0; i < len; i++) {
372@@ -155,7 +157,8 @@ std::string ToLower(const std::string &name) {
373 }
374 return rv;
375 }
376-std::string ToCamel(const std::string &name) {
377+
378+std::string ToCamel(compat::StringView name) {
379 std::string rv = "";
380 int len = name.length();
381 bool next_is_upper = true;
382@@ -172,7 +175,7 @@ std::string ToCamel(const std::string &name) {
383 return rv;
384 }
385
386-std::string OverrideFullName(const std::string &full_name, const google::protobuf::FileDescriptor* file) {
387+std::string OverrideFullName(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
388 const ProtobufCFileOptions opt = file->options().GetExtension(pb_c_file);
389 if (!opt.has_c_package())
390 return full_name;
391@@ -184,7 +187,7 @@ std::string OverrideFullName(const std::string &full_name, const google::protobu
392 return new_name + full_name.substr(file->package().length());
393 }
394
395-std::string FullNameToLower(const std::string &full_name, const google::protobuf::FileDescriptor* file) {
396+std::string FullNameToLower(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
397 std::vector<std::string> pieces;
398 SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces);
399 std::string rv = "";
400@@ -195,7 +198,8 @@ std::string FullNameToLower(const std::string &full_name, const google::protobuf
401 }
402 return rv;
403 }
404-std::string FullNameToUpper(const std::string &full_name, const google::protobuf::FileDescriptor* file) {
405+
406+std::string FullNameToUpper(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
407 std::vector<std::string> pieces;
408 SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces);
409 std::string rv = "";
410@@ -206,7 +210,8 @@ std::string FullNameToUpper(const std::string &full_name, const google::protobuf
411 }
412 return rv;
413 }
414-std::string FullNameToC(const std::string &full_name, const google::protobuf::FileDescriptor* file) {
415+
416+std::string FullNameToC(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
417 std::vector<std::string> pieces;
418 SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces);
419 std::string rv = "";
420@@ -248,7 +253,7 @@ void PrintComment(google::protobuf::io::Printer* printer, std::string comment)
421 }
422 }
423
424-std::string ConvertToSpaces(const std::string &input) {
425+std::string ConvertToSpaces(compat::StringView input) {
426 return std::string(input.size(), ' ');
427 }
428
429@@ -259,8 +264,7 @@ int compare_name_indices_by_name(const void *a, const void *b)
430 return strcmp (ni_a->name, ni_b->name);
431 }
432
433-
434-std::string CEscape(const std::string& src);
435+std::string CEscape(compat::StringView src);
436
437 const char* const kKeywordList[] = {
438 "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case",
439@@ -300,7 +304,7 @@ std::string FieldDeprecated(const google::protobuf::FieldDescriptor* field) {
440 return "";
441 }
442
443-std::string StripProto(const std::string& filename) {
444+std::string StripProto(compat::StringView filename) {
445 if (HasSuffixString(filename, ".protodevel")) {
446 return StripSuffixString(filename, ".protodevel");
447 } else {
448@@ -309,7 +313,7 @@ std::string StripProto(const std::string& filename) {
449 }
450
451 // Convert a file name into a valid identifier.
452-std::string FilenameIdentifier(const std::string& filename) {
453+std::string FilenameIdentifier(compat::StringView filename) {
454 std::string result;
455 for (unsigned i = 0; i < filename.size(); i++) {
456 if (isalnum(filename[i])) {
457@@ -335,7 +339,7 @@ std::string GetLabelName(google::protobuf::FieldDescriptor::Label label) {
458 }
459
460 unsigned
461-WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, const std::string &name)
462+WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, compat::StringView name)
463 {
464 std::map<std::string, std::string> vars;
465 vars["name"] = name;
466@@ -389,7 +393,7 @@ WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *
467 // ----------------------------------------------------------------------
468 template <typename ITR>
469 static inline
470-void SplitStringToIteratorUsing(const std::string& full,
471+void SplitStringToIteratorUsing(compat::StringView full,
472 const char* delim,
473 ITR& result) {
474 // Optimize the common case where delim is a single character.
475@@ -422,7 +426,7 @@ void SplitStringToIteratorUsing(const std::string& full,
476 }
477 }
478
479-void SplitStringUsing(const std::string& full,
480+void SplitStringUsing(compat::StringView full,
481 const char* delim,
482 std::vector<std::string>* result) {
483 std::back_insert_iterator< std::vector<std::string> > it(*result);
484@@ -435,7 +439,6 @@ char* FastHexToBuffer(int i, char* buffer)
485 return buffer;
486 }
487
488-
489 static int CEscapeInternal(const char* src, int src_len, char* dest,
490 int dest_len, bool use_hex) {
491 const char* src_end = src + src_len;
492@@ -478,7 +481,8 @@ static int CEscapeInternal(const char* src, int src_len, char* dest,
493 dest[used] = '\0'; // doesn't count towards return value though
494 return used;
495 }
496-std::string CEscape(const std::string& src) {
497+
498+std::string CEscape(compat::StringView src) {
499 const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
500 std::unique_ptr<char[]> dest(new char[dest_length]);
501 const int len = CEscapeInternal(src.data(), src.size(),
502diff --git a/protoc-gen-c/c_helpers.h b/protoc-gen-c/c_helpers.h
503index 377d4272..ccd39ca2 100644
504--- a/protoc-gen-c/c_helpers.h
505+++ b/protoc-gen-c/c_helpers.h
506@@ -73,6 +73,8 @@
507
508 #include <protobuf-c/protobuf-c.pb.h>
509
510+#include "compat.h"
511+
512 namespace protobuf_c {
513
514 // --- Borrowed from stubs. ---
515@@ -84,11 +86,10 @@ template <typename T> std::string SimpleItoa(T n) {
516
517 std::string SimpleFtoa(float f);
518 std::string SimpleDtoa(double f);
519-void SplitStringUsing(const std::string &str, const char *delim, std::vector<std::string> *out);
520-std::string CEscape(const std::string& src);
521-std::string StringReplace(const std::string& s, const std::string& oldsub, const std::string& newsub, bool replace_all);
522-inline bool HasSuffixString(const std::string& str, const std::string& suffix) { return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; }
523-inline std::string StripSuffixString(const std::string& str, const std::string& suffix) { if (HasSuffixString(str, suffix)) { return str.substr(0, str.size() - suffix.size()); } else { return str; } }
524+void SplitStringUsing(compat::StringView str, const char *delim, std::vector<std::string> *out);
525+std::string CEscape(compat::StringView src);
526+inline bool HasSuffixString(compat::StringView str, compat::StringView suffix) { return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; }
527+inline std::string StripSuffixString(compat::StringView str, compat::StringView suffix) { if (HasSuffixString(str, suffix)) { return str.substr(0, str.size() - suffix.size()); } else { return str; } }
528 char* FastHexToBuffer(int i, char* buffer);
529
530
531@@ -110,31 +111,31 @@ inline const google::protobuf::Descriptor* FieldScope(const google::protobuf::Fi
532
533 // convert a CamelCase class name into an all uppercase affair
534 // with underscores separating words, e.g. MyClass becomes MY_CLASS.
535-std::string CamelToUpper(const std::string &class_name);
536-std::string CamelToLower(const std::string &class_name);
537+std::string CamelToUpper(compat::StringView class_name);
538+std::string CamelToLower(compat::StringView class_name);
539
540 // lowercased, underscored name to camel case
541-std::string ToCamel(const std::string &name);
542+std::string ToCamel(compat::StringView name);
543
544 // lowercase the string
545-std::string ToLower(const std::string &class_name);
546-std::string ToUpper(const std::string &class_name);
547+std::string ToLower(compat::StringView class_name);
548+std::string ToUpper(compat::StringView class_name);
549
550 // full_name() to lowercase with underscores
551-std::string FullNameToLower(const std::string &full_name, const google::protobuf::FileDescriptor *file);
552-std::string FullNameToUpper(const std::string &full_name, const google::protobuf::FileDescriptor *file);
553+std::string FullNameToLower(compat::StringView full_name, const google::protobuf::FileDescriptor *file);
554+std::string FullNameToUpper(compat::StringView full_name, const google::protobuf::FileDescriptor *file);
555
556 // full_name() to c-typename (with underscores for packages, otherwise camel case)
557-std::string FullNameToC(const std::string &class_name, const google::protobuf::FileDescriptor *file);
558+std::string FullNameToC(compat::StringView class_name, const google::protobuf::FileDescriptor *file);
559
560 // Splits, indents, formats, and prints comment lines
561 void PrintComment(google::protobuf::io::Printer* printer, std::string comment);
562
563 // make a string of spaces as long as input
564-std::string ConvertToSpaces(const std::string &input);
565+std::string ConvertToSpaces(compat::StringView input);
566
567 // Strips ".proto" or ".protodevel" from the end of a filename.
568-std::string StripProto(const std::string& filename);
569+std::string StripProto(compat::StringView filename);
570
571 // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
572 // Note: non-built-in type names will be qualified, meaning they will start
573@@ -148,15 +149,14 @@ const char* PrimitiveTypeName(google::protobuf::FieldDescriptor::CppType type);
574 const char* DeclaredTypeMethodName(google::protobuf::FieldDescriptor::Type type);
575
576 // Convert a file name into a valid identifier.
577-std::string FilenameIdentifier(const std::string& filename);
578+std::string FilenameIdentifier(compat::StringView filename);
579
580 // return 'required', 'optional', or 'repeated'
581 std::string GetLabelName(google::protobuf::FieldDescriptor::Label label);
582
583-
584 // write IntRanges entries for a bunch of sorted values.
585 // returns the number of ranges there are to bsearch.
586-unsigned WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, const std::string &name);
587+unsigned WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, compat::StringView name);
588
589 struct NameIndex
590 {
591
592From 75f1c32cc429233a3726358c999009f9ea373b45 Mon Sep 17 00:00:00 2001
593From: Robert Edmonds <edmonds@users.noreply.github.com>
594Date: Sat, 8 Feb 2025 20:25:43 -0500
595Subject: [PATCH 05/11] Convert string views to owned strings where necessary
596
597---
598 protoc-gen-c/c_enum.cc | 2 +-
599 protoc-gen-c/c_enum_field.cc | 2 +-
600 protoc-gen-c/c_helpers.cc | 8 ++++----
601 protoc-gen-c/c_helpers.h | 3 +--
602 4 files changed, 7 insertions(+), 8 deletions(-)
603
604diff --git a/protoc-gen-c/c_enum.cc b/protoc-gen-c/c_enum.cc
605index 9212ab82..311e4c86 100644
606--- a/protoc-gen-c/c_enum.cc
607+++ b/protoc-gen-c/c_enum.cc
608@@ -152,7 +152,7 @@ void EnumGenerator::GenerateValueInitializer(google::protobuf::io::Printer *prin
609 descriptor_->file()->options().optimize_for() ==
610 google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
611 vars["enum_value_name"] = vd->name();
612- vars["c_enum_value_name"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()) + "__" + vd->name();
613+ vars["c_enum_value_name"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()) + "__" + std::string(vd->name());
614 vars["value"] = SimpleItoa(vd->number());
615 if (optimize_code_size)
616 printer->Print(vars, " { NULL, NULL, $value$ }, /* CODE_SIZE */\n");
617diff --git a/protoc-gen-c/c_enum_field.cc b/protoc-gen-c/c_enum_field.cc
618index 0926ae59..c3111f50 100644
619--- a/protoc-gen-c/c_enum_field.cc
620+++ b/protoc-gen-c/c_enum_field.cc
621@@ -78,7 +78,7 @@ void SetEnumVariables(const google::protobuf::FieldDescriptor* descriptor,
622 (*variables)["type"] = FullNameToC(descriptor->enum_type()->full_name(), descriptor->enum_type()->file());
623 const google::protobuf::EnumValueDescriptor* default_value = descriptor->default_value_enum();
624 (*variables)["default"] = FullNameToUpper(default_value->type()->full_name(), default_value->type()->file())
625- + "__" + default_value->name();
626+ + "__" + std::string(default_value->name());
627 (*variables)["deprecated"] = FieldDeprecated(descriptor);
628 }
629
630diff --git a/protoc-gen-c/c_helpers.cc b/protoc-gen-c/c_helpers.cc
631index c759c8c2..1aecef93 100644
632--- a/protoc-gen-c/c_helpers.cc
633+++ b/protoc-gen-c/c_helpers.cc
634@@ -178,13 +178,13 @@ std::string ToCamel(compat::StringView name) {
635 std::string OverrideFullName(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
636 const ProtobufCFileOptions opt = file->options().GetExtension(pb_c_file);
637 if (!opt.has_c_package())
638- return full_name;
639+ return std::string(full_name);
640
641 std::string new_name = opt.c_package();
642 if (file->package().empty())
643 new_name += ".";
644
645- return new_name + full_name.substr(file->package().length());
646+ return new_name + std::string(full_name.substr(file->package().length()));
647 }
648
649 std::string FullNameToLower(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
650@@ -418,10 +418,10 @@ void SplitStringToIteratorUsing(compat::StringView full,
651 while (begin_index != std::string::npos) {
652 end_index = full.find_first_of(delim, begin_index);
653 if (end_index == std::string::npos) {
654- *result++ = full.substr(begin_index);
655+ *result++ = std::string(full.substr(begin_index));
656 return;
657 }
658- *result++ = full.substr(begin_index, (end_index - begin_index));
659+ *result++ = std::string(full.substr(begin_index, (end_index - begin_index)));
660 begin_index = full.find_first_not_of(delim, end_index);
661 }
662 }
663diff --git a/protoc-gen-c/c_helpers.h b/protoc-gen-c/c_helpers.h
664index ccd39ca2..985e4db6 100644
665--- a/protoc-gen-c/c_helpers.h
666+++ b/protoc-gen-c/c_helpers.h
667@@ -89,10 +89,9 @@ std::string SimpleDtoa(double f);
668 void SplitStringUsing(compat::StringView str, const char *delim, std::vector<std::string> *out);
669 std::string CEscape(compat::StringView src);
670 inline bool HasSuffixString(compat::StringView str, compat::StringView suffix) { return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; }
671-inline std::string StripSuffixString(compat::StringView str, compat::StringView suffix) { if (HasSuffixString(str, suffix)) { return str.substr(0, str.size() - suffix.size()); } else { return str; } }
672+inline std::string StripSuffixString(compat::StringView str, compat::StringView suffix) { if (HasSuffixString(str, suffix)) { return std::string(str.substr(0, str.size() - suffix.size())); } else { return std::string(str); } }
673 char* FastHexToBuffer(int i, char* buffer);
674
675-
676 // Get the (unqualified) name that should be used for this field in C code.
677 // The name is coerced to lower-case to emulate proto1 behavior. People
678 // should be using lowercase-with-underscores style for proto field names
679
680From 0edca93db369fb84f01cc0d4e3ee4cd6c2ad7f4f Mon Sep 17 00:00:00 2001
681From: Robert Edmonds <edmonds@users.noreply.github.com>
682Date: Sat, 8 Feb 2025 20:39:11 -0500
683Subject: [PATCH 06/11] Convert various uses of `const char *` to
684 `compat::StringView`
685
686Also replace some uses of arrays manually allocated with new/delete with
687uses of `std::vector`.
688---
689 protoc-gen-c/c_enum.cc | 35 ++++++++++++++++++-----------------
690 protoc-gen-c/c_helpers.cc | 2 +-
691 protoc-gen-c/c_helpers.h | 2 +-
692 protoc-gen-c/c_message.cc | 28 ++++++++++++----------------
693 protoc-gen-c/c_service.cc | 19 +++++++++----------
694 5 files changed, 41 insertions(+), 45 deletions(-)
695
696diff --git a/protoc-gen-c/c_enum.cc b/protoc-gen-c/c_enum.cc
697index 311e4c86..c7839edd 100644
698--- a/protoc-gen-c/c_enum.cc
699+++ b/protoc-gen-c/c_enum.cc
700@@ -142,7 +142,7 @@ struct ValueIndex
701 int value;
702 unsigned index;
703 unsigned final_index; /* index in uniqified array of values */
704- const char *name;
705+ compat::StringView name;
706 };
707 void EnumGenerator::GenerateValueInitializer(google::protobuf::io::Printer *printer, int index)
708 {
709@@ -176,7 +176,7 @@ static int compare_value_indices_by_name(const void *a, const void *b)
710 {
711 const ValueIndex *vi_a = (const ValueIndex *) a;
712 const ValueIndex *vi_b = (const ValueIndex *) b;
713- return strcmp (vi_a->name, vi_b->name);
714+ return vi_a->name.compare(vi_b->name);
715 }
716
717 void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printer) {
718@@ -194,18 +194,20 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
719
720 // Sort by name and value, dropping duplicate values if they appear later.
721 // TODO: use a c++ paradigm for this!
722- NameIndex *name_index = new NameIndex[descriptor_->value_count()];
723- ValueIndex *value_index = new ValueIndex[descriptor_->value_count()];
724- for (int j = 0; j < descriptor_->value_count(); j++) {
725+ std::vector<ValueIndex> value_index;
726+ for (unsigned j = 0; j < descriptor_->value_count(); j++) {
727 const google::protobuf::EnumValueDescriptor *vd = descriptor_->value(j);
728- name_index[j].index = j;
729- name_index[j].name = vd->name().c_str();
730- value_index[j].index = j;
731- value_index[j].value = vd->number();
732- value_index[j].name = vd->name().c_str();
733+ value_index.push_back({
734+ .value = vd->number(),
735+ .index = j,
736+ .final_index = 0,
737+ .name = vd->name(),
738+ });
739 }
740- qsort(value_index, descriptor_->value_count(),
741- sizeof(ValueIndex), compare_value_indices_by_value_then_index);
742+ qsort(&value_index[0],
743+ value_index.size(),
744+ sizeof(ValueIndex),
745+ compare_value_indices_by_value_then_index);
746
747 // only record unique values
748 int n_unique_values;
749@@ -275,8 +277,10 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
750 vars["n_ranges"] = SimpleItoa(n_ranges);
751
752 if (!optimize_code_size) {
753- qsort(value_index, descriptor_->value_count(),
754- sizeof(ValueIndex), compare_value_indices_by_name);
755+ qsort(&value_index[0],
756+ value_index.size(),
757+ sizeof(ValueIndex),
758+ compare_value_indices_by_name);
759 printer->Print(vars,
760 "static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n"
761 "{\n");
762@@ -319,9 +323,6 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
763 " NULL,NULL,NULL,NULL /* reserved[1234] */\n"
764 "};\n");
765 }
766-
767- delete[] value_index;
768- delete[] name_index;
769 }
770
771 } // namespace protobuf_c
772diff --git a/protoc-gen-c/c_helpers.cc b/protoc-gen-c/c_helpers.cc
773index 1aecef93..dec9ce28 100644
774--- a/protoc-gen-c/c_helpers.cc
775+++ b/protoc-gen-c/c_helpers.cc
776@@ -261,7 +261,7 @@ int compare_name_indices_by_name(const void *a, const void *b)
777 {
778 const NameIndex *ni_a = (const NameIndex *) a;
779 const NameIndex *ni_b = (const NameIndex *) b;
780- return strcmp (ni_a->name, ni_b->name);
781+ return ni_a->name.compare(ni_b->name);
782 }
783
784 std::string CEscape(compat::StringView src);
785diff --git a/protoc-gen-c/c_helpers.h b/protoc-gen-c/c_helpers.h
786index 985e4db6..69369997 100644
787--- a/protoc-gen-c/c_helpers.h
788+++ b/protoc-gen-c/c_helpers.h
789@@ -160,7 +160,7 @@ unsigned WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, co
790 struct NameIndex
791 {
792 unsigned index;
793- const char *name;
794+ compat::StringView name;
795 };
796 int compare_name_indices_by_name(const void*, const void*);
797
798diff --git a/protoc-gen-c/c_message.cc b/protoc-gen-c/c_message.cc
799index 46413873..7252923c 100644
800--- a/protoc-gen-c/c_message.cc
801+++ b/protoc-gen-c/c_message.cc
802@@ -567,27 +567,26 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
803 "static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n"
804 "{\n");
805 printer->Indent();
806- const google::protobuf::FieldDescriptor **sorted_fields = new const google::protobuf::FieldDescriptor *[descriptor_->field_count()];
807+
808+ std::vector<const google::protobuf::FieldDescriptor*> sorted_fields;
809 for (int i = 0; i < descriptor_->field_count(); i++) {
810- sorted_fields[i] = descriptor_->field(i);
811+ sorted_fields.push_back(descriptor_->field(i));
812 }
813- qsort (sorted_fields, descriptor_->field_count(),
814+ qsort(&sorted_fields[0], sorted_fields.size(),
815 sizeof(const google::protobuf::FieldDescriptor*),
816 compare_pfields_by_number);
817- for (int i = 0; i < descriptor_->field_count(); i++) {
818- const google::protobuf::FieldDescriptor* field = sorted_fields[i];
819+ for (auto field : sorted_fields) {
820 field_generators_.get(field).GenerateDescriptorInitializer(printer);
821 }
822 printer->Outdent();
823 printer->Print(vars, "};\n");
824
825 if (!optimize_code_size) {
826- NameIndex *field_indices = new NameIndex [descriptor_->field_count()];
827- for (int i = 0; i < descriptor_->field_count(); i++) {
828- field_indices[i].name = sorted_fields[i]->name().c_str();
829- field_indices[i].index = i;
830+ std::vector<NameIndex> field_indices;
831+ for (unsigned i = 0; i < descriptor_->field_count(); i++) {
832+ field_indices.push_back({ .index = i, .name = sorted_fields[i]->name() });
833 }
834- qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex),
835+ qsort(&field_indices[0], field_indices.size(), sizeof(NameIndex),
836 compare_name_indices_by_name);
837 printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n");
838 for (int i = 0; i < descriptor_->field_count(); i++) {
839@@ -596,19 +595,16 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
840 printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
841 }
842 printer->Print("};\n");
843- delete[] field_indices;
844 }
845
846 // create range initializers
847- int *values = new int[descriptor_->field_count()];
848+ std::vector<int> values;
849 for (int i = 0; i < descriptor_->field_count(); i++) {
850- values[i] = sorted_fields[i]->number();
851+ values.push_back(sorted_fields[i]->number());
852 }
853 int n_ranges = WriteIntRanges(printer,
854- descriptor_->field_count(), values,
855+ descriptor_->field_count(), &values[0],
856 vars["lcclassname"] + "__number_ranges");
857- delete [] values;
858- delete [] sorted_fields;
859
860 vars["n_ranges"] = SimpleItoa(n_ranges);
861 } else {
862diff --git a/protoc-gen-c/c_service.cc b/protoc-gen-c/c_service.cc
863index ee4d4a95..2c3ddcf3 100644
864--- a/protoc-gen-c/c_service.cc
865+++ b/protoc-gen-c/c_service.cc
866@@ -184,19 +184,19 @@ void ServiceGenerator::GenerateInit(google::protobuf::io::Printer* printer)
867 "}\n");
868 }
869
870-struct MethodIndexAndName { unsigned i; const char *name; };
871+struct MethodIndexAndName { unsigned i; compat::StringView name; };
872 static int
873 compare_method_index_and_name_by_name (const void *a, const void *b)
874 {
875 const MethodIndexAndName *ma = (const MethodIndexAndName *) a;
876 const MethodIndexAndName *mb = (const MethodIndexAndName *) b;
877- return strcmp (ma->name, mb->name);
878+ return ma->name.compare(mb->name);
879 }
880
881 void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer* printer)
882 {
883 int n_methods = descriptor_->method_count();
884- MethodIndexAndName *mi_array = new MethodIndexAndName[n_methods];
885+ std::vector<MethodIndexAndName> mi_array;
886
887 bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
888 descriptor_->file()->options().optimize_for() ==
889@@ -205,7 +205,7 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
890 vars_["n_methods"] = SimpleItoa(n_methods);
891 printer->Print(vars_, "static const ProtobufCMethodDescriptor $lcfullname$__method_descriptors[$n_methods$] =\n"
892 "{\n");
893- for (int i = 0; i < n_methods; i++) {
894+ for (unsigned i = 0; i < n_methods; i++) {
895 const google::protobuf::MethodDescriptor* method = descriptor_->method(i);
896 vars_["method"] = method->name();
897 vars_["input_descriptor"] = "&" + FullNameToLower(method->input_type()->full_name(), method->input_type()->file()) + "__descriptor";
898@@ -217,14 +217,15 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
899 printer->Print(vars_,
900 " { \"$method$\", $input_descriptor$, $output_descriptor$ },\n");
901 }
902- mi_array[i].i = i;
903- mi_array[i].name = method->name().c_str();
904+ mi_array.push_back({i, method->name()});
905 }
906 printer->Print(vars_, "};\n");
907
908 if (!optimize_code_size) {
909- qsort ((void*)mi_array, n_methods, sizeof (MethodIndexAndName),
910- compare_method_index_and_name_by_name);
911+ qsort(&mi_array[0],
912+ mi_array.size(),
913+ sizeof(MethodIndexAndName),
914+ compare_method_index_and_name_by_name);
915 printer->Print(vars_, "const unsigned $lcfullname$__method_indices_by_name[] = {\n");
916 for (int i = 0; i < n_methods; i++) {
917 vars_["i"] = SimpleItoa(mi_array[i].i);
918@@ -258,8 +259,6 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
919 " $lcfullname$__method_indices_by_name\n"
920 "};\n");
921 }
922-
923- delete[] mi_array;
924 }
925
926 void ServiceGenerator::GenerateCallersImplementations(google::protobuf::io::Printer* printer)
927
928From ebeddac1a746393a16d9ba4cf80e3d12c3ab7d7f Mon Sep 17 00:00:00 2001
929From: Robert Edmonds <edmonds@users.noreply.github.com>
930Date: Sat, 8 Feb 2025 20:56:48 -0500
931Subject: [PATCH 07/11] Fix indentation of
932 MessageGenerator::GenerateMessageDescriptor()
933
934---
935 protoc-gen-c/c_message.cc | 321 +++++++++++++++++++-------------------
936 1 file changed, 159 insertions(+), 162 deletions(-)
937
938diff --git a/protoc-gen-c/c_message.cc b/protoc-gen-c/c_message.cc
939index 7252923c..2a3b2a2f 100644
940--- a/protoc-gen-c/c_message.cc
941+++ b/protoc-gen-c/c_message.cc
942@@ -461,199 +461,196 @@ GenerateHelperFunctionDefinitions(google::protobuf::io::Printer* printer,
943
944 void MessageGenerator::
945 GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init) {
946- std::map<std::string, std::string> vars;
947- vars["fullname"] = descriptor_->full_name();
948- vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
949- vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
950- vars["shortname"] = ToCamel(descriptor_->name());
951- vars["n_fields"] = SimpleItoa(descriptor_->field_count());
952- vars["packagename"] = descriptor_->file()->package();
953-
954- bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
955- descriptor_->file()->options().optimize_for() ==
956- google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
957-
958- const ProtobufCMessageOptions opt =
959- descriptor_->options().GetExtension(pb_c_msg);
960- // Override parent settings, if needed
961- if (opt.has_gen_init_helpers())
962- gen_init = opt.gen_init_helpers();
963-
964- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
965- nested_generators_[i]->GenerateMessageDescriptor(printer, gen_init);
966- }
967+ std::map<std::string, std::string> vars;
968+ vars["fullname"] = descriptor_->full_name();
969+ vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
970+ vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
971+ vars["shortname"] = ToCamel(descriptor_->name());
972+ vars["n_fields"] = SimpleItoa(descriptor_->field_count());
973+ vars["packagename"] = descriptor_->file()->package();
974
975- for (int i = 0; i < descriptor_->enum_type_count(); i++) {
976- enum_generators_[i]->GenerateEnumDescriptor(printer);
977- }
978+ bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
979+ descriptor_->file()->options().optimize_for() ==
980+ google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
981
982- for (int i = 0; i < descriptor_->field_count(); i++) {
983- const google::protobuf::FieldDescriptor* fd = descriptor_->field(i);
984- if (fd->has_default_value()) {
985- field_generators_.get(fd).GenerateDefaultValueImplementations(printer);
986- }
987- }
988+ const ProtobufCMessageOptions opt = descriptor_->options().GetExtension(pb_c_msg);
989+ // Override parent settings, if needed
990+ if (opt.has_gen_init_helpers()) {
991+ gen_init = opt.gen_init_helpers();
992+ }
993
994- for (int i = 0; i < descriptor_->field_count(); i++) {
995- const google::protobuf::FieldDescriptor* fd = descriptor_->field(i);
996- const ProtobufCFieldOptions opt = fd->options().GetExtension(pb_c_field);
997- if (fd->has_default_value()) {
998-
999- bool already_defined = false;
1000- vars["name"] = fd->name();
1001- vars["lcname"] = CamelToLower(fd->name());
1002- vars["maybe_static"] = "static ";
1003- vars["field_dv_ctype_suffix"] = "";
1004- vars["default_value"] = field_generators_.get(fd).GetDefaultValue();
1005- switch (fd->cpp_type()) {
1006- case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
1007- vars["field_dv_ctype"] = "int32_t";
1008- break;
1009- case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
1010- vars["field_dv_ctype"] = "int64_t";
1011- break;
1012- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
1013- vars["field_dv_ctype"] = "uint32_t";
1014- break;
1015- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
1016- vars["field_dv_ctype"] = "uint64_t";
1017- break;
1018- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
1019- vars["field_dv_ctype"] = "float";
1020- break;
1021- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
1022- vars["field_dv_ctype"] = "double";
1023- break;
1024- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
1025- vars["field_dv_ctype"] = "protobuf_c_boolean";
1026- break;
1027-
1028- case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
1029- // NOTE: not supported by protobuf
1030- vars["maybe_static"] = "";
1031- vars["field_dv_ctype"] = "{ ... }";
1032- GOOGLE_LOG(FATAL) << "Messages can't have default values!";
1033- break;
1034- case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
1035- if (fd->type() == google::protobuf::FieldDescriptor::TYPE_BYTES || opt.string_as_bytes())
1036- {
1037- vars["field_dv_ctype"] = "ProtobufCBinaryData";
1038- }
1039- else /* STRING type */
1040- {
1041- already_defined = true;
1042- vars["maybe_static"] = "";
1043- vars["field_dv_ctype"] = "char";
1044- vars["field_dv_ctype_suffix"] = "[]";
1045- }
1046- break;
1047- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
1048- {
1049- const google::protobuf::EnumValueDescriptor* vd = fd->default_value_enum();
1050- vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name(), vd->type()->file());
1051- break;
1052- }
1053- default:
1054- GOOGLE_LOG(FATAL) << "Unknown CPPTYPE";
1055- break;
1056- }
1057- if (!already_defined)
1058- printer->Print(vars, "$maybe_static$const $field_dv_ctype$ $lcclassname$__$lcname$__default_value$field_dv_ctype_suffix$ = $default_value$;\n");
1059- }
1060- }
1061+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1062+ nested_generators_[i]->GenerateMessageDescriptor(printer, gen_init);
1063+ }
1064
1065- if ( descriptor_->field_count() ) {
1066- printer->Print(vars,
1067- "static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n"
1068- "{\n");
1069- printer->Indent();
1070+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
1071+ enum_generators_[i]->GenerateEnumDescriptor(printer);
1072+ }
1073
1074- std::vector<const google::protobuf::FieldDescriptor*> sorted_fields;
1075 for (int i = 0; i < descriptor_->field_count(); i++) {
1076- sorted_fields.push_back(descriptor_->field(i));
1077- }
1078- qsort(&sorted_fields[0], sorted_fields.size(),
1079- sizeof(const google::protobuf::FieldDescriptor*),
1080- compare_pfields_by_number);
1081- for (auto field : sorted_fields) {
1082- field_generators_.get(field).GenerateDescriptorInitializer(printer);
1083+ const google::protobuf::FieldDescriptor* fd = descriptor_->field(i);
1084+ if (fd->has_default_value()) {
1085+ field_generators_.get(fd).GenerateDefaultValueImplementations(printer);
1086+ }
1087 }
1088- printer->Outdent();
1089- printer->Print(vars, "};\n");
1090
1091- if (!optimize_code_size) {
1092- std::vector<NameIndex> field_indices;
1093- for (unsigned i = 0; i < descriptor_->field_count(); i++) {
1094- field_indices.push_back({ .index = i, .name = sorted_fields[i]->name() });
1095+ for (int i = 0; i < descriptor_->field_count(); i++) {
1096+ const google::protobuf::FieldDescriptor* fd = descriptor_->field(i);
1097+ const ProtobufCFieldOptions opt = fd->options().GetExtension(pb_c_field);
1098+ if (fd->has_default_value()) {
1099+ bool already_defined = false;
1100+ vars["name"] = fd->name();
1101+ vars["lcname"] = CamelToLower(fd->name());
1102+ vars["maybe_static"] = "static ";
1103+ vars["field_dv_ctype_suffix"] = "";
1104+ vars["default_value"] = field_generators_.get(fd).GetDefaultValue();
1105+ switch (fd->cpp_type()) {
1106+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
1107+ vars["field_dv_ctype"] = "int32_t";
1108+ break;
1109+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
1110+ vars["field_dv_ctype"] = "int64_t";
1111+ break;
1112+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
1113+ vars["field_dv_ctype"] = "uint32_t";
1114+ break;
1115+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
1116+ vars["field_dv_ctype"] = "uint64_t";
1117+ break;
1118+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
1119+ vars["field_dv_ctype"] = "float";
1120+ break;
1121+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
1122+ vars["field_dv_ctype"] = "double";
1123+ break;
1124+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
1125+ vars["field_dv_ctype"] = "protobuf_c_boolean";
1126+ break;
1127+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
1128+ // NOTE: not supported by protobuf
1129+ vars["maybe_static"] = "";
1130+ vars["field_dv_ctype"] = "{ ... }";
1131+ GOOGLE_LOG(FATAL) << "Messages can't have default values!";
1132+ break;
1133+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
1134+ if (fd->type() == google::protobuf::FieldDescriptor::TYPE_BYTES || opt.string_as_bytes()) {
1135+ vars["field_dv_ctype"] = "ProtobufCBinaryData";
1136+ } else {
1137+ /* STRING type */
1138+ already_defined = true;
1139+ vars["maybe_static"] = "";
1140+ vars["field_dv_ctype"] = "char";
1141+ vars["field_dv_ctype_suffix"] = "[]";
1142+ }
1143+ break;
1144+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
1145+ const google::protobuf::EnumValueDescriptor* vd = fd->default_value_enum();
1146+ vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name(), vd->type()->file());
1147+ break;
1148+ }
1149+ default:
1150+ GOOGLE_LOG(FATAL) << "Unknown CPPTYPE";
1151+ break;
1152+ }
1153+ if (!already_defined) {
1154+ printer->Print(vars, "$maybe_static$const $field_dv_ctype$ $lcclassname$__$lcname$__default_value$field_dv_ctype_suffix$ = $default_value$;\n");
1155+ }
1156 }
1157- qsort(&field_indices[0], field_indices.size(), sizeof(NameIndex),
1158- compare_name_indices_by_name);
1159- printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n");
1160+ }
1161+
1162+ if (descriptor_->field_count()) {
1163+ printer->Print(vars,
1164+ "static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n"
1165+ "{\n");
1166+ printer->Indent();
1167+
1168+ std::vector<const google::protobuf::FieldDescriptor*> sorted_fields;
1169 for (int i = 0; i < descriptor_->field_count(); i++) {
1170- vars["index"] = SimpleItoa(field_indices[i].index);
1171- vars["name"] = field_indices[i].name;
1172- printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
1173+ sorted_fields.push_back(descriptor_->field(i));
1174 }
1175- printer->Print("};\n");
1176- }
1177+ qsort(&sorted_fields[0],
1178+ sorted_fields.size(),
1179+ sizeof(const google::protobuf::FieldDescriptor*),
1180+ compare_pfields_by_number);
1181+ for (auto field : sorted_fields) {
1182+ field_generators_.get(field).GenerateDescriptorInitializer(printer);
1183+ }
1184+ printer->Outdent();
1185+ printer->Print(vars, "};\n");
1186
1187- // create range initializers
1188- std::vector<int> values;
1189- for (int i = 0; i < descriptor_->field_count(); i++) {
1190- values.push_back(sorted_fields[i]->number());
1191- }
1192- int n_ranges = WriteIntRanges(printer,
1193- descriptor_->field_count(), &values[0],
1194- vars["lcclassname"] + "__number_ranges");
1195+ if (!optimize_code_size) {
1196+ std::vector<NameIndex> field_indices;
1197+ for (unsigned i = 0; i < descriptor_->field_count(); i++) {
1198+ field_indices.push_back({ .index = i, .name = sorted_fields[i]->name() });
1199+ }
1200+ qsort(&field_indices[0],
1201+ field_indices.size(),
1202+ sizeof(NameIndex),
1203+ compare_name_indices_by_name);
1204+ printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n");
1205+ for (int i = 0; i < descriptor_->field_count(); i++) {
1206+ vars["index"] = SimpleItoa(field_indices[i].index);
1207+ vars["name"] = field_indices[i].name;
1208+ printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
1209+ }
1210+ printer->Print("};\n");
1211+ }
1212
1213- vars["n_ranges"] = SimpleItoa(n_ranges);
1214- } else {
1215- /* MS compiler can't handle arrays with zero size and empty
1216- * initialization list. Furthermore it is an extension of GCC only but
1217- * not a standard. */
1218- vars["n_ranges"] = "0";
1219- printer->Print(vars,
1220- "#define $lcclassname$__field_descriptors NULL\n"
1221- "#define $lcclassname$__field_indices_by_name NULL\n"
1222- "#define $lcclassname$__number_ranges NULL\n");
1223+ // create range initializers
1224+ std::vector<int> values;
1225+ for (int i = 0; i < descriptor_->field_count(); i++) {
1226+ values.push_back(sorted_fields[i]->number());
1227 }
1228+ int n_ranges = WriteIntRanges(printer,
1229+ descriptor_->field_count(),
1230+ &values[0],
1231+ vars["lcclassname"] + "__number_ranges");
1232+
1233+ vars["n_ranges"] = SimpleItoa(n_ranges);
1234+ } else {
1235+ /* MS compiler can't handle arrays with zero size and empty
1236+ * initialization list. Furthermore it is an extension of GCC only but
1237+ * not a standard. */
1238+ vars["n_ranges"] = "0";
1239+ printer->Print(vars,
1240+ "#define $lcclassname$__field_descriptors NULL\n"
1241+ "#define $lcclassname$__field_indices_by_name NULL\n"
1242+ "#define $lcclassname$__number_ranges NULL\n");
1243+ }
1244
1245 printer->Print(vars,
1246- "const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n"
1247- "{\n"
1248- " PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n");
1249+ "const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n"
1250+ "{\n"
1251+ " PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n");
1252 if (optimize_code_size) {
1253 printer->Print(" NULL,NULL,NULL,NULL, /* CODE_SIZE */\n");
1254 } else {
1255 printer->Print(vars,
1256- " \"$fullname$\",\n"
1257- " \"$shortname$\",\n"
1258- " \"$classname$\",\n"
1259- " \"$packagename$\",\n");
1260+ " \"$fullname$\",\n"
1261+ " \"$shortname$\",\n"
1262+ " \"$classname$\",\n"
1263+ " \"$packagename$\",\n");
1264 }
1265 printer->Print(vars,
1266- " sizeof($classname$),\n"
1267- " $n_fields$,\n"
1268- " $lcclassname$__field_descriptors,\n");
1269+ " sizeof($classname$),\n"
1270+ " $n_fields$,\n"
1271+ " $lcclassname$__field_descriptors,\n");
1272 if (optimize_code_size) {
1273 printer->Print(" NULL, /* CODE_SIZE */\n");
1274 } else {
1275- printer->Print(vars,
1276- " $lcclassname$__field_indices_by_name,\n");
1277+ printer->Print(vars, " $lcclassname$__field_indices_by_name,\n");
1278 }
1279 printer->Print(vars,
1280- " $n_ranges$,"
1281- " $lcclassname$__number_ranges,\n");
1282+ " $n_ranges$,"
1283+ " $lcclassname$__number_ranges,\n");
1284 if (gen_init) {
1285- printer->Print(vars,
1286- " (ProtobufCMessageInit) $lcclassname$__init,\n");
1287+ printer->Print(vars, " (ProtobufCMessageInit) $lcclassname$__init,\n");
1288 } else {
1289- printer->Print(vars,
1290- " NULL, /* gen_init_helpers = false */\n");
1291+ printer->Print(vars, " NULL, /* gen_init_helpers = false */\n");
1292 }
1293 printer->Print(vars,
1294- " NULL,NULL,NULL /* reserved[123] */\n"
1295- "};\n");
1296+ " NULL,NULL,NULL /* reserved[123] */\n"
1297+ "};\n");
1298 }
1299
1300 int MessageGenerator::GetOneofUnionOrder(const google::protobuf::FieldDescriptor* fd)
1301
1302From c59b146aee2d97091ca2adeecd3f2741cb7f0082 Mon Sep 17 00:00:00 2001
1303From: Robert Edmonds <edmonds@users.noreply.github.com>
1304Date: Sat, 8 Feb 2025 21:10:37 -0500
1305Subject: [PATCH 08/11] compat: Use absl::string_view instead of
1306 google::protobuf::internal::DescriptorStringView
1307
1308Even though google::protobuf::internal::DescriptorStringView is exposed
1309in public protobuf headers, it's probably not a good idea to rely on an
1310"internal" typedef.
1311
1312According to https://protobuf.dev/news/2024-10-02/#descriptor-apis:
1313
1314 v30 will update return types in descriptor (such as full_name) to be
1315 absl::string_view.
1316
1317So `absl::string_view` is probably the right type to use here.
1318---
1319 protoc-gen-c/compat.h | 6 +++++-
1320 1 file changed, 5 insertions(+), 1 deletion(-)
1321
1322diff --git a/protoc-gen-c/compat.h b/protoc-gen-c/compat.h
1323index fe8041b5..a70cef34 100644
1324--- a/protoc-gen-c/compat.h
1325+++ b/protoc-gen-c/compat.h
1326@@ -37,12 +37,16 @@
1327 # define GOOGLE_LOG ABSL_LOG
1328 #endif
1329
1330+#if GOOGLE_PROTOBUF_VERSION >= 6030000
1331+# include <absl/strings/string_view.h>
1332+#endif
1333+
1334 namespace protobuf_c {
1335
1336 namespace compat {
1337
1338 #if GOOGLE_PROTOBUF_VERSION >= 6030000
1339-typedef google::protobuf::internal::DescriptorStringView StringView;
1340+typedef absl::string_view StringView;
1341 #else
1342 typedef const std::string& StringView;
1343 #endif
1344
1345From 9c56038fd9d3cc2552c297457d7a66efe5cbd2c7 Mon Sep 17 00:00:00 2001
1346From: Robert Edmonds <edmonds@users.noreply.github.com>
1347Date: Sat, 8 Feb 2025 21:37:30 -0500
1348Subject: [PATCH 09/11] Makefile.am: Add compat.h to
1349 protoc_gen_c_protoc_gen_c_SOURCES
1350
1351---
1352 Makefile.am | 1 +
1353 1 file changed, 1 insertion(+)
1354
1355diff --git a/Makefile.am b/Makefile.am
1356index 77aa9d99..26d19f16 100644
1357--- a/Makefile.am
1358+++ b/Makefile.am
1359@@ -102,6 +102,7 @@ protoc_gen_c_protoc_gen_c_SOURCES = \
1360 protoc-gen-c/c_service.h \
1361 protoc-gen-c/c_string_field.cc \
1362 protoc-gen-c/c_string_field.h \
1363+ protoc-gen-c/compat.h \
1364 protobuf-c/protobuf-c.pb.cc \
1365 protobuf-c/protobuf-c.pb.h \
1366 protoc-gen-c/main.cc
1367
1368From 4ebd5cd8238d1f2ac6291b8c8925f34e16ce2123 Mon Sep 17 00:00:00 2001
1369From: Robert Edmonds <edmonds@users.noreply.github.com>
1370Date: Sat, 8 Feb 2025 21:38:07 -0500
1371Subject: [PATCH 10/11] compat: Conditionalize the include of <string>
1372
1373It is only needed on older protobuf versions where absl::string_view is
1374not being used.
1375---
1376 protoc-gen-c/compat.h | 4 ++--
1377 1 file changed, 2 insertions(+), 2 deletions(-)
1378
1379diff --git a/protoc-gen-c/compat.h b/protoc-gen-c/compat.h
1380index a70cef34..f6ace7cb 100644
1381--- a/protoc-gen-c/compat.h
1382+++ b/protoc-gen-c/compat.h
1383@@ -28,8 +28,6 @@
1384 #ifndef PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
1385 #define PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
1386
1387-#include <string>
1388-
1389 #if GOOGLE_PROTOBUF_VERSION >= 4022000
1390 # define GOOGLE_ARRAYSIZE ABSL_ARRAYSIZE
1391 # define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
1392@@ -39,6 +37,8 @@
1393
1394 #if GOOGLE_PROTOBUF_VERSION >= 6030000
1395 # include <absl/strings/string_view.h>
1396+#else
1397+# include <string>
1398 #endif
1399
1400 namespace protobuf_c {
1401
1402From 9a6b35e1e6956fb5cb044910448049b7a5339244 Mon Sep 17 00:00:00 2001
1403From: Robert Edmonds <edmonds@users.noreply.github.com>
1404Date: Sat, 8 Feb 2025 21:44:42 -0500
1405Subject: [PATCH 11/11] Cater to Microsoft Visual C++
1406
1407Apparently MSVC doesn't support designated initializers for some reason.
1408---
1409 protoc-gen-c/c_enum.cc | 9 ++-------
1410 protoc-gen-c/c_message.cc | 2 +-
1411 2 files changed, 3 insertions(+), 8 deletions(-)
1412
1413diff --git a/protoc-gen-c/c_enum.cc b/protoc-gen-c/c_enum.cc
1414index c7839edd..1940ba9d 100644
1415--- a/protoc-gen-c/c_enum.cc
1416+++ b/protoc-gen-c/c_enum.cc
1417@@ -195,14 +195,9 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
1418 // Sort by name and value, dropping duplicate values if they appear later.
1419 // TODO: use a c++ paradigm for this!
1420 std::vector<ValueIndex> value_index;
1421- for (unsigned j = 0; j < descriptor_->value_count(); j++) {
1422+ for (int j = 0; j < descriptor_->value_count(); j++) {
1423 const google::protobuf::EnumValueDescriptor *vd = descriptor_->value(j);
1424- value_index.push_back({
1425- .value = vd->number(),
1426- .index = j,
1427- .final_index = 0,
1428- .name = vd->name(),
1429- });
1430+ value_index.push_back({ vd->number(), (unsigned)j, 0, vd->name() });
1431 }
1432 qsort(&value_index[0],
1433 value_index.size(),
1434diff --git a/protoc-gen-c/c_message.cc b/protoc-gen-c/c_message.cc
1435index 2a3b2a2f..94889179 100644
1436--- a/protoc-gen-c/c_message.cc
1437+++ b/protoc-gen-c/c_message.cc
1438@@ -581,7 +581,7 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
1439 if (!optimize_code_size) {
1440 std::vector<NameIndex> field_indices;
1441 for (unsigned i = 0; i < descriptor_->field_count(); i++) {
1442- field_indices.push_back({ .index = i, .name = sorted_fields[i]->name() });
1443+ field_indices.push_back({ i, sorted_fields[i]->name() });
1444 }
1445 qsort(&field_indices[0],
1446 field_indices.size(),