Unverified Commit 25174818 authored by Robert Edmonds's avatar Robert Edmonds Committed by GitHub

Merge pull request #762 from protobuf-c/edmonds/google-protobuf-30-fixes

Chase compatibility issues with Google protobuf 30.0-rc1
parents 185beed2 9a6b35e1
......@@ -102,6 +102,7 @@ protoc_gen_c_protoc_gen_c_SOURCES = \
protoc-gen-c/c_service.h \
protoc-gen-c/c_string_field.cc \
protoc-gen-c/c_string_field.h \
protoc-gen-c/compat.h \
protobuf-c/protobuf-c.pb.cc \
protobuf-c/protobuf-c.pb.h \
protoc-gen-c/main.cc
......
......@@ -142,7 +142,7 @@ struct ValueIndex
int value;
unsigned index;
unsigned final_index; /* index in uniqified array of values */
const char *name;
compat::StringView name;
};
void EnumGenerator::GenerateValueInitializer(google::protobuf::io::Printer *printer, int index)
{
......@@ -152,7 +152,7 @@ void EnumGenerator::GenerateValueInitializer(google::protobuf::io::Printer *prin
descriptor_->file()->options().optimize_for() ==
google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
vars["enum_value_name"] = vd->name();
vars["c_enum_value_name"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()) + "__" + vd->name();
vars["c_enum_value_name"] = FullNameToUpper(descriptor_->full_name(), descriptor_->file()) + "__" + std::string(vd->name());
vars["value"] = SimpleItoa(vd->number());
if (optimize_code_size)
printer->Print(vars, " { NULL, NULL, $value$ }, /* CODE_SIZE */\n");
......@@ -176,7 +176,7 @@ static int compare_value_indices_by_name(const void *a, const void *b)
{
const ValueIndex *vi_a = (const ValueIndex *) a;
const ValueIndex *vi_b = (const ValueIndex *) b;
return strcmp (vi_a->name, vi_b->name);
return vi_a->name.compare(vi_b->name);
}
void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printer) {
......@@ -194,18 +194,15 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
// Sort by name and value, dropping duplicate values if they appear later.
// TODO: use a c++ paradigm for this!
NameIndex *name_index = new NameIndex[descriptor_->value_count()];
ValueIndex *value_index = new ValueIndex[descriptor_->value_count()];
std::vector<ValueIndex> value_index;
for (int j = 0; j < descriptor_->value_count(); j++) {
const google::protobuf::EnumValueDescriptor *vd = descriptor_->value(j);
name_index[j].index = j;
name_index[j].name = vd->name().c_str();
value_index[j].index = j;
value_index[j].value = vd->number();
value_index[j].name = vd->name().c_str();
value_index.push_back({ vd->number(), (unsigned)j, 0, vd->name() });
}
qsort(value_index, descriptor_->value_count(),
sizeof(ValueIndex), compare_value_indices_by_value_then_index);
qsort(&value_index[0],
value_index.size(),
sizeof(ValueIndex),
compare_value_indices_by_value_then_index);
// only record unique values
int n_unique_values;
......@@ -275,8 +272,10 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
vars["n_ranges"] = SimpleItoa(n_ranges);
if (!optimize_code_size) {
qsort(value_index, descriptor_->value_count(),
sizeof(ValueIndex), compare_value_indices_by_name);
qsort(&value_index[0],
value_index.size(),
sizeof(ValueIndex),
compare_value_indices_by_name);
printer->Print(vars,
"static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n"
"{\n");
......@@ -319,9 +318,6 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
" NULL,NULL,NULL,NULL /* reserved[1234] */\n"
"};\n");
}
delete[] value_index;
delete[] name_index;
}
} // namespace protobuf_c
......@@ -78,7 +78,7 @@ void SetEnumVariables(const google::protobuf::FieldDescriptor* descriptor,
(*variables)["type"] = FullNameToC(descriptor->enum_type()->full_name(), descriptor->enum_type()->file());
const google::protobuf::EnumValueDescriptor* default_value = descriptor->default_value_enum();
(*variables)["default"] = FullNameToUpper(default_value->type()->full_name(), default_value->type()->file())
+ "__" + default_value->name();
+ "__" + std::string(default_value->name());
(*variables)["deprecated"] = FieldDeprecated(descriptor);
}
......
......@@ -74,6 +74,7 @@
#include "c_message_field.h"
#include "c_primitive_field.h"
#include "c_string_field.h"
#include "compat.h"
namespace protobuf_c {
......
This diff is collapsed.
......@@ -73,6 +73,8 @@
#include <protobuf-c/protobuf-c.pb.h>
#include "compat.h"
namespace protobuf_c {
// --- Borrowed from stubs. ---
......@@ -84,14 +86,12 @@ template <typename T> std::string SimpleItoa(T n) {
std::string SimpleFtoa(float f);
std::string SimpleDtoa(double f);
void SplitStringUsing(const std::string &str, const char *delim, std::vector<std::string> *out);
std::string CEscape(const std::string& src);
std::string StringReplace(const std::string& s, const std::string& oldsub, const std::string& newsub, bool replace_all);
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; }
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; } }
void SplitStringUsing(compat::StringView str, const char *delim, std::vector<std::string> *out);
std::string CEscape(compat::StringView src);
inline bool HasSuffixString(compat::StringView str, compat::StringView suffix) { return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; }
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); } }
char* FastHexToBuffer(int i, char* buffer);
// Get the (unqualified) name that should be used for this field in C code.
// The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names
......@@ -110,31 +110,31 @@ inline const google::protobuf::Descriptor* FieldScope(const google::protobuf::Fi
// convert a CamelCase class name into an all uppercase affair
// with underscores separating words, e.g. MyClass becomes MY_CLASS.
std::string CamelToUpper(const std::string &class_name);
std::string CamelToLower(const std::string &class_name);
std::string CamelToUpper(compat::StringView class_name);
std::string CamelToLower(compat::StringView class_name);
// lowercased, underscored name to camel case
std::string ToCamel(const std::string &name);
std::string ToCamel(compat::StringView name);
// lowercase the string
std::string ToLower(const std::string &class_name);
std::string ToUpper(const std::string &class_name);
std::string ToLower(compat::StringView class_name);
std::string ToUpper(compat::StringView class_name);
// full_name() to lowercase with underscores
std::string FullNameToLower(const std::string &full_name, const google::protobuf::FileDescriptor *file);
std::string FullNameToUpper(const std::string &full_name, const google::protobuf::FileDescriptor *file);
std::string FullNameToLower(compat::StringView full_name, const google::protobuf::FileDescriptor *file);
std::string FullNameToUpper(compat::StringView full_name, const google::protobuf::FileDescriptor *file);
// full_name() to c-typename (with underscores for packages, otherwise camel case)
std::string FullNameToC(const std::string &class_name, const google::protobuf::FileDescriptor *file);
std::string FullNameToC(compat::StringView class_name, const google::protobuf::FileDescriptor *file);
// Splits, indents, formats, and prints comment lines
void PrintComment(google::protobuf::io::Printer* printer, std::string comment);
// make a string of spaces as long as input
std::string ConvertToSpaces(const std::string &input);
std::string ConvertToSpaces(compat::StringView input);
// Strips ".proto" or ".protodevel" from the end of a filename.
std::string StripProto(const std::string& filename);
std::string StripProto(compat::StringView filename);
// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
// Note: non-built-in type names will be qualified, meaning they will start
......@@ -148,23 +148,19 @@ const char* PrimitiveTypeName(google::protobuf::FieldDescriptor::CppType type);
const char* DeclaredTypeMethodName(google::protobuf::FieldDescriptor::Type type);
// Convert a file name into a valid identifier.
std::string FilenameIdentifier(const std::string& filename);
// Return the name of the BuildDescriptors() function for a given file.
std::string GlobalBuildDescriptorsName(const std::string& filename);
std::string FilenameIdentifier(compat::StringView filename);
// return 'required', 'optional', or 'repeated'
std::string GetLabelName(google::protobuf::FieldDescriptor::Label label);
// write IntRanges entries for a bunch of sorted values.
// returns the number of ranges there are to bsearch.
unsigned WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, const std::string &name);
unsigned WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, compat::StringView name);
struct NameIndex
{
unsigned index;
const char *name;
compat::StringView name;
};
int compare_name_indices_by_name(const void*, const void*);
......@@ -186,16 +182,6 @@ inline int FieldSyntax(const google::protobuf::FieldDescriptor* field) {
return 2;
}
// Work around changes in protobuf >= 22.x without breaking compilation against
// older protobuf versions.
#if GOOGLE_PROTOBUF_VERSION >= 4022000
# define GOOGLE_ARRAYSIZE ABSL_ARRAYSIZE
# define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
# define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
# define GOOGLE_DCHECK_GE ABSL_DCHECK_GE
# define GOOGLE_LOG ABSL_LOG
#endif
} // namespace protobuf_c
#endif // PROTOBUF_C_PROTOC_GEN_C_C_HELPERS_H__
......@@ -78,6 +78,7 @@
#include "c_extension.h"
#include "c_helpers.h"
#include "c_message.h"
#include "compat.h"
namespace protobuf_c {
......@@ -472,11 +473,11 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
descriptor_->file()->options().optimize_for() ==
google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
const ProtobufCMessageOptions opt =
descriptor_->options().GetExtension(pb_c_msg);
const ProtobufCMessageOptions opt = descriptor_->options().GetExtension(pb_c_msg);
// Override parent settings, if needed
if (opt.has_gen_init_helpers())
if (opt.has_gen_init_helpers()) {
gen_init = opt.gen_init_helpers();
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateMessageDescriptor(printer, gen_init);
......@@ -497,7 +498,6 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
const google::protobuf::FieldDescriptor* fd = descriptor_->field(i);
const ProtobufCFieldOptions opt = fd->options().GetExtension(pb_c_field);
if (fd->has_default_value()) {
bool already_defined = false;
vars["name"] = fd->name();
vars["lcname"] = CamelToLower(fd->name());
......@@ -526,7 +526,6 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
vars["field_dv_ctype"] = "protobuf_c_boolean";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
// NOTE: not supported by protobuf
vars["maybe_static"] = "";
......@@ -534,20 +533,17 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
GOOGLE_LOG(FATAL) << "Messages can't have default values!";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
if (fd->type() == google::protobuf::FieldDescriptor::TYPE_BYTES || opt.string_as_bytes())
{
if (fd->type() == google::protobuf::FieldDescriptor::TYPE_BYTES || opt.string_as_bytes()) {
vars["field_dv_ctype"] = "ProtobufCBinaryData";
}
else /* STRING type */
{
} else {
/* STRING type */
already_defined = true;
vars["maybe_static"] = "";
vars["field_dv_ctype"] = "char";
vars["field_dv_ctype_suffix"] = "[]";
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
{
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
const google::protobuf::EnumValueDescriptor* vd = fd->default_value_enum();
vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name(), vd->type()->file());
break;
......@@ -556,37 +552,40 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
GOOGLE_LOG(FATAL) << "Unknown CPPTYPE";
break;
}
if (!already_defined)
if (!already_defined) {
printer->Print(vars, "$maybe_static$const $field_dv_ctype$ $lcclassname$__$lcname$__default_value$field_dv_ctype_suffix$ = $default_value$;\n");
}
}
}
if ( descriptor_->field_count() ) {
if (descriptor_->field_count()) {
printer->Print(vars,
"static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n"
"{\n");
printer->Indent();
const google::protobuf::FieldDescriptor **sorted_fields = new const google::protobuf::FieldDescriptor *[descriptor_->field_count()];
std::vector<const google::protobuf::FieldDescriptor*> sorted_fields;
for (int i = 0; i < descriptor_->field_count(); i++) {
sorted_fields[i] = descriptor_->field(i);
sorted_fields.push_back(descriptor_->field(i));
}
qsort (sorted_fields, descriptor_->field_count(),
qsort(&sorted_fields[0],
sorted_fields.size(),
sizeof(const google::protobuf::FieldDescriptor*),
compare_pfields_by_number);
for (int i = 0; i < descriptor_->field_count(); i++) {
const google::protobuf::FieldDescriptor* field = sorted_fields[i];
for (auto field : sorted_fields) {
field_generators_.get(field).GenerateDescriptorInitializer(printer);
}
printer->Outdent();
printer->Print(vars, "};\n");
if (!optimize_code_size) {
NameIndex *field_indices = new NameIndex [descriptor_->field_count()];
for (int i = 0; i < descriptor_->field_count(); i++) {
field_indices[i].name = sorted_fields[i]->name().c_str();
field_indices[i].index = i;
std::vector<NameIndex> field_indices;
for (unsigned i = 0; i < descriptor_->field_count(); i++) {
field_indices.push_back({ i, sorted_fields[i]->name() });
}
qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex),
qsort(&field_indices[0],
field_indices.size(),
sizeof(NameIndex),
compare_name_indices_by_name);
printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
......@@ -595,19 +594,17 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
}
printer->Print("};\n");
delete[] field_indices;
}
// create range initializers
int *values = new int[descriptor_->field_count()];
std::vector<int> values;
for (int i = 0; i < descriptor_->field_count(); i++) {
values[i] = sorted_fields[i]->number();
values.push_back(sorted_fields[i]->number());
}
int n_ranges = WriteIntRanges(printer,
descriptor_->field_count(), values,
descriptor_->field_count(),
&values[0],
vars["lcclassname"] + "__number_ranges");
delete [] values;
delete [] sorted_fields;
vars["n_ranges"] = SimpleItoa(n_ranges);
} else {
......@@ -641,18 +638,15 @@ GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init)
if (optimize_code_size) {
printer->Print(" NULL, /* CODE_SIZE */\n");
} else {
printer->Print(vars,
" $lcclassname$__field_indices_by_name,\n");
printer->Print(vars, " $lcclassname$__field_indices_by_name,\n");
}
printer->Print(vars,
" $n_ranges$,"
" $lcclassname$__number_ranges,\n");
if (gen_init) {
printer->Print(vars,
" (ProtobufCMessageInit) $lcclassname$__init,\n");
printer->Print(vars, " (ProtobufCMessageInit) $lcclassname$__init,\n");
} else {
printer->Print(vars,
" NULL, /* gen_init_helpers = false */\n");
printer->Print(vars, " NULL, /* gen_init_helpers = false */\n");
}
printer->Print(vars,
" NULL,NULL,NULL /* reserved[123] */\n"
......
......@@ -67,6 +67,7 @@
#include "c_helpers.h"
#include "c_primitive_field.h"
#include "compat.h"
namespace protobuf_c {
......
......@@ -184,19 +184,19 @@ void ServiceGenerator::GenerateInit(google::protobuf::io::Printer* printer)
"}\n");
}
struct MethodIndexAndName { unsigned i; const char *name; };
struct MethodIndexAndName { unsigned i; compat::StringView name; };
static int
compare_method_index_and_name_by_name (const void *a, const void *b)
{
const MethodIndexAndName *ma = (const MethodIndexAndName *) a;
const MethodIndexAndName *mb = (const MethodIndexAndName *) b;
return strcmp (ma->name, mb->name);
return ma->name.compare(mb->name);
}
void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer* printer)
{
int n_methods = descriptor_->method_count();
MethodIndexAndName *mi_array = new MethodIndexAndName[n_methods];
std::vector<MethodIndexAndName> mi_array;
bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
descriptor_->file()->options().optimize_for() ==
......@@ -205,7 +205,7 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
vars_["n_methods"] = SimpleItoa(n_methods);
printer->Print(vars_, "static const ProtobufCMethodDescriptor $lcfullname$__method_descriptors[$n_methods$] =\n"
"{\n");
for (int i = 0; i < n_methods; i++) {
for (unsigned i = 0; i < n_methods; i++) {
const google::protobuf::MethodDescriptor* method = descriptor_->method(i);
vars_["method"] = method->name();
vars_["input_descriptor"] = "&" + FullNameToLower(method->input_type()->full_name(), method->input_type()->file()) + "__descriptor";
......@@ -217,13 +217,14 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
printer->Print(vars_,
" { \"$method$\", $input_descriptor$, $output_descriptor$ },\n");
}
mi_array[i].i = i;
mi_array[i].name = method->name().c_str();
mi_array.push_back({i, method->name()});
}
printer->Print(vars_, "};\n");
if (!optimize_code_size) {
qsort ((void*)mi_array, n_methods, sizeof (MethodIndexAndName),
qsort(&mi_array[0],
mi_array.size(),
sizeof(MethodIndexAndName),
compare_method_index_and_name_by_name);
printer->Print(vars_, "const unsigned $lcfullname$__method_indices_by_name[] = {\n");
for (int i = 0; i < n_methods; i++) {
......@@ -258,8 +259,6 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
" $lcfullname$__method_indices_by_name\n"
"};\n");
}
delete[] mi_array;
}
void ServiceGenerator::GenerateCallersImplementations(google::protobuf::io::Printer* printer)
......
// Copyright (c) 2008-2025, Dave Benson and the protobuf-c authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
#define PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
#if GOOGLE_PROTOBUF_VERSION >= 4022000
# define GOOGLE_ARRAYSIZE ABSL_ARRAYSIZE
# define GOOGLE_CHECK_EQ ABSL_CHECK_EQ
# define GOOGLE_DCHECK_GE ABSL_DCHECK_GE
# define GOOGLE_LOG ABSL_LOG
#endif
#if GOOGLE_PROTOBUF_VERSION >= 6030000
# include <absl/strings/string_view.h>
#else
# include <string>
#endif
namespace protobuf_c {
namespace compat {
#if GOOGLE_PROTOBUF_VERSION >= 6030000
typedef absl::string_view StringView;
#else
typedef const std::string& StringView;
#endif
} // namespace compat
} // namespace protobuf_c
#endif // PROTOBUF_C_PROTOC_GEN_C_COMPAT_H__
......@@ -32,6 +32,7 @@
#include "c_generator.h"
#include "c_helpers.h"
#include "compat.h"
int main(int argc, char* argv[]) {
protobuf_c::CGenerator c_generator;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment