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 = \ ...@@ -102,6 +102,7 @@ protoc_gen_c_protoc_gen_c_SOURCES = \
protoc-gen-c/c_service.h \ protoc-gen-c/c_service.h \
protoc-gen-c/c_string_field.cc \ protoc-gen-c/c_string_field.cc \
protoc-gen-c/c_string_field.h \ protoc-gen-c/c_string_field.h \
protoc-gen-c/compat.h \
protobuf-c/protobuf-c.pb.cc \ protobuf-c/protobuf-c.pb.cc \
protobuf-c/protobuf-c.pb.h \ protobuf-c/protobuf-c.pb.h \
protoc-gen-c/main.cc protoc-gen-c/main.cc
......
...@@ -142,7 +142,7 @@ struct ValueIndex ...@@ -142,7 +142,7 @@ struct ValueIndex
int value; int value;
unsigned index; unsigned index;
unsigned final_index; /* index in uniqified array of values */ 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) void EnumGenerator::GenerateValueInitializer(google::protobuf::io::Printer *printer, int index)
{ {
...@@ -152,7 +152,7 @@ void EnumGenerator::GenerateValueInitializer(google::protobuf::io::Printer *prin ...@@ -152,7 +152,7 @@ void EnumGenerator::GenerateValueInitializer(google::protobuf::io::Printer *prin
descriptor_->file()->options().optimize_for() == descriptor_->file()->options().optimize_for() ==
google::protobuf::FileOptions_OptimizeMode_CODE_SIZE; google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
vars["enum_value_name"] = vd->name(); 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()); vars["value"] = SimpleItoa(vd->number());
if (optimize_code_size) if (optimize_code_size)
printer->Print(vars, " { NULL, NULL, $value$ }, /* CODE_SIZE */\n"); 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) ...@@ -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_a = (const ValueIndex *) a;
const ValueIndex *vi_b = (const ValueIndex *) b; 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) { void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printer) {
...@@ -194,18 +194,15 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe ...@@ -194,18 +194,15 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
// Sort by name and value, dropping duplicate values if they appear later. // Sort by name and value, dropping duplicate values if they appear later.
// TODO: use a c++ paradigm for this! // TODO: use a c++ paradigm for this!
NameIndex *name_index = new NameIndex[descriptor_->value_count()]; std::vector<ValueIndex> value_index;
ValueIndex *value_index = new ValueIndex[descriptor_->value_count()];
for (int j = 0; j < descriptor_->value_count(); j++) { for (int j = 0; j < descriptor_->value_count(); j++) {
const google::protobuf::EnumValueDescriptor *vd = descriptor_->value(j); const google::protobuf::EnumValueDescriptor *vd = descriptor_->value(j);
name_index[j].index = j; value_index.push_back({ vd->number(), (unsigned)j, 0, vd->name() });
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();
} }
qsort(value_index, descriptor_->value_count(), qsort(&value_index[0],
sizeof(ValueIndex), compare_value_indices_by_value_then_index); value_index.size(),
sizeof(ValueIndex),
compare_value_indices_by_value_then_index);
// only record unique values // only record unique values
int n_unique_values; int n_unique_values;
...@@ -275,8 +272,10 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe ...@@ -275,8 +272,10 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
vars["n_ranges"] = SimpleItoa(n_ranges); vars["n_ranges"] = SimpleItoa(n_ranges);
if (!optimize_code_size) { if (!optimize_code_size) {
qsort(value_index, descriptor_->value_count(), qsort(&value_index[0],
sizeof(ValueIndex), compare_value_indices_by_name); value_index.size(),
sizeof(ValueIndex),
compare_value_indices_by_name);
printer->Print(vars, printer->Print(vars,
"static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n" "static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n"
"{\n"); "{\n");
...@@ -319,9 +318,6 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe ...@@ -319,9 +318,6 @@ void EnumGenerator::GenerateEnumDescriptor(google::protobuf::io::Printer* printe
" NULL,NULL,NULL,NULL /* reserved[1234] */\n" " NULL,NULL,NULL,NULL /* reserved[1234] */\n"
"};\n"); "};\n");
} }
delete[] value_index;
delete[] name_index;
} }
} // namespace protobuf_c } // namespace protobuf_c
...@@ -78,7 +78,7 @@ void SetEnumVariables(const google::protobuf::FieldDescriptor* descriptor, ...@@ -78,7 +78,7 @@ void SetEnumVariables(const google::protobuf::FieldDescriptor* descriptor,
(*variables)["type"] = FullNameToC(descriptor->enum_type()->full_name(), descriptor->enum_type()->file()); (*variables)["type"] = FullNameToC(descriptor->enum_type()->full_name(), descriptor->enum_type()->file());
const google::protobuf::EnumValueDescriptor* default_value = descriptor->default_value_enum(); const google::protobuf::EnumValueDescriptor* default_value = descriptor->default_value_enum();
(*variables)["default"] = FullNameToUpper(default_value->type()->full_name(), default_value->type()->file()) (*variables)["default"] = FullNameToUpper(default_value->type()->full_name(), default_value->type()->file())
+ "__" + default_value->name(); + "__" + std::string(default_value->name());
(*variables)["deprecated"] = FieldDeprecated(descriptor); (*variables)["deprecated"] = FieldDeprecated(descriptor);
} }
......
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
#include "c_message_field.h" #include "c_message_field.h"
#include "c_primitive_field.h" #include "c_primitive_field.h"
#include "c_string_field.h" #include "c_string_field.h"
#include "compat.h"
namespace protobuf_c { namespace protobuf_c {
......
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/common.h>
#include "c_helpers.h" #include "c_helpers.h"
#include "compat.h"
namespace protobuf_c { namespace protobuf_c {
...@@ -89,20 +90,13 @@ namespace protobuf_c { ...@@ -89,20 +90,13 @@ namespace protobuf_c {
#pragma warning(disable:4996) #pragma warning(disable:4996)
#endif #endif
std::string DotsToUnderscores(const std::string& name) {
return StringReplace(name, ".", "_", true);
}
std::string DotsToColons(const std::string& name) {
return StringReplace(name, ".", "::", true);
}
std::string SimpleFtoa(float f) { std::string SimpleFtoa(float f) {
char buf[100]; char buf[100];
snprintf(buf,sizeof(buf),"%.*g", FLT_DIG, f); snprintf(buf,sizeof(buf),"%.*g", FLT_DIG, f);
buf[sizeof(buf)-1] = 0; /* should NOT be necessary */ buf[sizeof(buf)-1] = 0; /* should NOT be necessary */
return buf; return buf;
} }
std::string SimpleDtoa(double d) { std::string SimpleDtoa(double d) {
char buf[100]; char buf[100];
snprintf(buf,sizeof(buf),"%.*g", DBL_DIG, d); snprintf(buf,sizeof(buf),"%.*g", DBL_DIG, d);
...@@ -110,7 +104,7 @@ std::string SimpleDtoa(double d) { ...@@ -110,7 +104,7 @@ std::string SimpleDtoa(double d) {
return buf; return buf;
} }
std::string CamelToUpper(const std::string &name) { std::string CamelToUpper(compat::StringView name) {
bool was_upper = true; // suppress initial _ bool was_upper = true; // suppress initial _
std::string rv = ""; std::string rv = "";
int len = name.length(); int len = name.length();
...@@ -127,7 +121,8 @@ std::string CamelToUpper(const std::string &name) { ...@@ -127,7 +121,8 @@ std::string CamelToUpper(const std::string &name) {
} }
return rv; return rv;
} }
std::string CamelToLower(const std::string &name) {
std::string CamelToLower(compat::StringView name) {
bool was_upper = true; // suppress initial _ bool was_upper = true; // suppress initial _
std::string rv = ""; std::string rv = "";
int len = name.length(); int len = name.length();
...@@ -145,8 +140,7 @@ std::string CamelToLower(const std::string &name) { ...@@ -145,8 +140,7 @@ std::string CamelToLower(const std::string &name) {
return rv; return rv;
} }
std::string ToUpper(compat::StringView name) {
std::string ToUpper(const std::string &name) {
std::string rv = ""; std::string rv = "";
int len = name.length(); int len = name.length();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
...@@ -154,7 +148,8 @@ std::string ToUpper(const std::string &name) { ...@@ -154,7 +148,8 @@ std::string ToUpper(const std::string &name) {
} }
return rv; return rv;
} }
std::string ToLower(const std::string &name) {
std::string ToLower(compat::StringView name) {
std::string rv = ""; std::string rv = "";
int len = name.length(); int len = name.length();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
...@@ -162,7 +157,8 @@ std::string ToLower(const std::string &name) { ...@@ -162,7 +157,8 @@ std::string ToLower(const std::string &name) {
} }
return rv; return rv;
} }
std::string ToCamel(const std::string &name) {
std::string ToCamel(compat::StringView name) {
std::string rv = ""; std::string rv = "";
int len = name.length(); int len = name.length();
bool next_is_upper = true; bool next_is_upper = true;
...@@ -179,19 +175,19 @@ std::string ToCamel(const std::string &name) { ...@@ -179,19 +175,19 @@ std::string ToCamel(const std::string &name) {
return rv; return rv;
} }
std::string OverrideFullName(const std::string &full_name, const google::protobuf::FileDescriptor* file) { std::string OverrideFullName(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
const ProtobufCFileOptions opt = file->options().GetExtension(pb_c_file); const ProtobufCFileOptions opt = file->options().GetExtension(pb_c_file);
if (!opt.has_c_package()) if (!opt.has_c_package())
return full_name; return std::string(full_name);
std::string new_name = opt.c_package(); std::string new_name = opt.c_package();
if (file->package().empty()) if (file->package().empty())
new_name += "."; new_name += ".";
return new_name + full_name.substr(file->package().length()); return new_name + std::string(full_name.substr(file->package().length()));
} }
std::string FullNameToLower(const std::string &full_name, const google::protobuf::FileDescriptor* file) { std::string FullNameToLower(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
std::vector<std::string> pieces; std::vector<std::string> pieces;
SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces); SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces);
std::string rv = ""; std::string rv = "";
...@@ -202,7 +198,8 @@ std::string FullNameToLower(const std::string &full_name, const google::protobuf ...@@ -202,7 +198,8 @@ std::string FullNameToLower(const std::string &full_name, const google::protobuf
} }
return rv; return rv;
} }
std::string FullNameToUpper(const std::string &full_name, const google::protobuf::FileDescriptor* file) {
std::string FullNameToUpper(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
std::vector<std::string> pieces; std::vector<std::string> pieces;
SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces); SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces);
std::string rv = ""; std::string rv = "";
...@@ -213,7 +210,8 @@ std::string FullNameToUpper(const std::string &full_name, const google::protobuf ...@@ -213,7 +210,8 @@ std::string FullNameToUpper(const std::string &full_name, const google::protobuf
} }
return rv; return rv;
} }
std::string FullNameToC(const std::string &full_name, const google::protobuf::FileDescriptor* file) {
std::string FullNameToC(compat::StringView full_name, const google::protobuf::FileDescriptor* file) {
std::vector<std::string> pieces; std::vector<std::string> pieces;
SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces); SplitStringUsing(OverrideFullName(full_name, file), ".", &pieces);
std::string rv = ""; std::string rv = "";
...@@ -255,7 +253,7 @@ void PrintComment(google::protobuf::io::Printer* printer, std::string comment) ...@@ -255,7 +253,7 @@ void PrintComment(google::protobuf::io::Printer* printer, std::string comment)
} }
} }
std::string ConvertToSpaces(const std::string &input) { std::string ConvertToSpaces(compat::StringView input) {
return std::string(input.size(), ' '); return std::string(input.size(), ' ');
} }
...@@ -263,11 +261,10 @@ int compare_name_indices_by_name(const void *a, const void *b) ...@@ -263,11 +261,10 @@ int compare_name_indices_by_name(const void *a, const void *b)
{ {
const NameIndex *ni_a = (const NameIndex *) a; const NameIndex *ni_a = (const NameIndex *) a;
const NameIndex *ni_b = (const NameIndex *) b; const NameIndex *ni_b = (const NameIndex *) b;
return strcmp (ni_a->name, ni_b->name); return ni_a->name.compare(ni_b->name);
} }
std::string CEscape(compat::StringView src);
std::string CEscape(const std::string& src);
const char* const kKeywordList[] = { const char* const kKeywordList[] = {
"and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case", "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case",
...@@ -307,7 +304,7 @@ std::string FieldDeprecated(const google::protobuf::FieldDescriptor* field) { ...@@ -307,7 +304,7 @@ std::string FieldDeprecated(const google::protobuf::FieldDescriptor* field) {
return ""; return "";
} }
std::string StripProto(const std::string& filename) { std::string StripProto(compat::StringView filename) {
if (HasSuffixString(filename, ".protodevel")) { if (HasSuffixString(filename, ".protodevel")) {
return StripSuffixString(filename, ".protodevel"); return StripSuffixString(filename, ".protodevel");
} else { } else {
...@@ -316,7 +313,7 @@ std::string StripProto(const std::string& filename) { ...@@ -316,7 +313,7 @@ std::string StripProto(const std::string& filename) {
} }
// Convert a file name into a valid identifier. // Convert a file name into a valid identifier.
std::string FilenameIdentifier(const std::string& filename) { std::string FilenameIdentifier(compat::StringView filename) {
std::string result; std::string result;
for (unsigned i = 0; i < filename.size(); i++) { for (unsigned i = 0; i < filename.size(); i++) {
if (isalnum(filename[i])) { if (isalnum(filename[i])) {
...@@ -332,11 +329,6 @@ std::string FilenameIdentifier(const std::string& filename) { ...@@ -332,11 +329,6 @@ std::string FilenameIdentifier(const std::string& filename) {
return result; return result;
} }
// Return the name of the BuildDescriptors() function for a given file.
std::string GlobalBuildDescriptorsName(const std::string& filename) {
return "proto_BuildDescriptors_" + FilenameIdentifier(filename);
}
std::string GetLabelName(google::protobuf::FieldDescriptor::Label label) { std::string GetLabelName(google::protobuf::FieldDescriptor::Label label) {
switch (label) { switch (label) {
case google::protobuf::FieldDescriptor::LABEL_OPTIONAL: return "optional"; case google::protobuf::FieldDescriptor::LABEL_OPTIONAL: return "optional";
...@@ -347,7 +339,7 @@ std::string GetLabelName(google::protobuf::FieldDescriptor::Label label) { ...@@ -347,7 +339,7 @@ std::string GetLabelName(google::protobuf::FieldDescriptor::Label label) {
} }
unsigned unsigned
WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, const std::string &name) WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *values, compat::StringView name)
{ {
std::map<std::string, std::string> vars; std::map<std::string, std::string> vars;
vars["name"] = name; vars["name"] = name;
...@@ -391,57 +383,6 @@ WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int * ...@@ -391,57 +383,6 @@ WriteIntRanges(google::protobuf::io::Printer* printer, int n_values, const int *
} }
} }
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx
// XXXXXXXXX this stuff is copied from strutils.cc !!!! XXXXXXXXXXXXXXXXXXXXXXXXXXXXx
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx
// ----------------------------------------------------------------------
// StringReplace()
// Replace the "old" pattern with the "new" pattern in a string,
// and append the result to "res". If replace_all is false,
// it only replaces the first instance of "old."
// ----------------------------------------------------------------------
void StringReplace(const std::string& s, const std::string& oldsub,
const std::string& newsub, bool replace_all,
std::string* res) {
if (oldsub.empty()) {
res->append(s); // if empty, append the given string.
return;
}
std::string::size_type start_pos = 0;
std::string::size_type pos;
do {
pos = s.find(oldsub, start_pos);
if (pos == std::string::npos) {
break;
}
res->append(s, start_pos, pos - start_pos);
res->append(newsub);
start_pos = pos + oldsub.size(); // start searching again after the "old"
} while (replace_all);
res->append(s, start_pos, s.length() - start_pos);
}
// ----------------------------------------------------------------------
// StringReplace()
// Give me a string and two patterns "old" and "new", and I replace
// the first instance of "old" in the string with "new", if it
// exists. If "global" is true; call this repeatedly until it
// fails. RETURN a new string, regardless of whether the replacement
// happened or not.
// ----------------------------------------------------------------------
std::string StringReplace(const std::string& s, const std::string& oldsub,
const std::string& newsub, bool replace_all) {
std::string ret;
StringReplace(s, oldsub, newsub, replace_all, &ret);
return ret;
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// SplitStringUsing() // SplitStringUsing()
// Split a string using a character delimiter. Append the components // Split a string using a character delimiter. Append the components
...@@ -452,7 +393,7 @@ std::string StringReplace(const std::string& s, const std::string& oldsub, ...@@ -452,7 +393,7 @@ std::string StringReplace(const std::string& s, const std::string& oldsub,
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
template <typename ITR> template <typename ITR>
static inline static inline
void SplitStringToIteratorUsing(const std::string& full, void SplitStringToIteratorUsing(compat::StringView full,
const char* delim, const char* delim,
ITR& result) { ITR& result) {
// Optimize the common case where delim is a single character. // Optimize the common case where delim is a single character.
...@@ -477,15 +418,15 @@ void SplitStringToIteratorUsing(const std::string& full, ...@@ -477,15 +418,15 @@ void SplitStringToIteratorUsing(const std::string& full,
while (begin_index != std::string::npos) { while (begin_index != std::string::npos) {
end_index = full.find_first_of(delim, begin_index); end_index = full.find_first_of(delim, begin_index);
if (end_index == std::string::npos) { if (end_index == std::string::npos) {
*result++ = full.substr(begin_index); *result++ = std::string(full.substr(begin_index));
return; return;
} }
*result++ = full.substr(begin_index, (end_index - begin_index)); *result++ = std::string(full.substr(begin_index, (end_index - begin_index)));
begin_index = full.find_first_not_of(delim, end_index); begin_index = full.find_first_not_of(delim, end_index);
} }
} }
void SplitStringUsing(const std::string& full, void SplitStringUsing(compat::StringView full,
const char* delim, const char* delim,
std::vector<std::string>* result) { std::vector<std::string>* result) {
std::back_insert_iterator< std::vector<std::string> > it(*result); std::back_insert_iterator< std::vector<std::string> > it(*result);
...@@ -498,7 +439,6 @@ char* FastHexToBuffer(int i, char* buffer) ...@@ -498,7 +439,6 @@ char* FastHexToBuffer(int i, char* buffer)
return buffer; return buffer;
} }
static int CEscapeInternal(const char* src, int src_len, char* dest, static int CEscapeInternal(const char* src, int src_len, char* dest,
int dest_len, bool use_hex) { int dest_len, bool use_hex) {
const char* src_end = src + src_len; const char* src_end = src + src_len;
...@@ -541,7 +481,8 @@ static int CEscapeInternal(const char* src, int src_len, char* dest, ...@@ -541,7 +481,8 @@ static int CEscapeInternal(const char* src, int src_len, char* dest,
dest[used] = '\0'; // doesn't count towards return value though dest[used] = '\0'; // doesn't count towards return value though
return used; return used;
} }
std::string CEscape(const std::string& src) {
std::string CEscape(compat::StringView src) {
const int dest_length = src.size() * 4 + 1; // Maximum possible expansion const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
std::unique_ptr<char[]> dest(new char[dest_length]); std::unique_ptr<char[]> dest(new char[dest_length]);
const int len = CEscapeInternal(src.data(), src.size(), const int len = CEscapeInternal(src.data(), src.size(),
......
...@@ -73,6 +73,8 @@ ...@@ -73,6 +73,8 @@
#include <protobuf-c/protobuf-c.pb.h> #include <protobuf-c/protobuf-c.pb.h>
#include "compat.h"
namespace protobuf_c { namespace protobuf_c {
// --- Borrowed from stubs. --- // --- Borrowed from stubs. ---
...@@ -84,14 +86,12 @@ template <typename T> std::string SimpleItoa(T n) { ...@@ -84,14 +86,12 @@ template <typename T> std::string SimpleItoa(T n) {
std::string SimpleFtoa(float f); std::string SimpleFtoa(float f);
std::string SimpleDtoa(double f); std::string SimpleDtoa(double f);
void SplitStringUsing(const std::string &str, const char *delim, std::vector<std::string> *out); void SplitStringUsing(compat::StringView str, const char *delim, std::vector<std::string> *out);
std::string CEscape(const std::string& src); std::string CEscape(compat::StringView src);
std::string StringReplace(const std::string& s, const std::string& oldsub, const std::string& newsub, bool replace_all); 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 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(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); } }
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; } }
char* FastHexToBuffer(int i, char* buffer); char* FastHexToBuffer(int i, char* buffer);
// Get the (unqualified) name that should be used for this field in C code. // 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 // The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names // 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 ...@@ -110,31 +110,31 @@ inline const google::protobuf::Descriptor* FieldScope(const google::protobuf::Fi
// convert a CamelCase class name into an all uppercase affair // convert a CamelCase class name into an all uppercase affair
// with underscores separating words, e.g. MyClass becomes MY_CLASS. // with underscores separating words, e.g. MyClass becomes MY_CLASS.
std::string CamelToUpper(const std::string &class_name); std::string CamelToUpper(compat::StringView class_name);
std::string CamelToLower(const std::string &class_name); std::string CamelToLower(compat::StringView class_name);
// lowercased, underscored name to camel case // lowercased, underscored name to camel case
std::string ToCamel(const std::string &name); std::string ToCamel(compat::StringView name);
// lowercase the string // lowercase the string
std::string ToLower(const std::string &class_name); std::string ToLower(compat::StringView class_name);
std::string ToUpper(const std::string &class_name); std::string ToUpper(compat::StringView class_name);
// full_name() to lowercase with underscores // full_name() to lowercase with underscores
std::string FullNameToLower(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(const std::string &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) // 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 // Splits, indents, formats, and prints comment lines
void PrintComment(google::protobuf::io::Printer* printer, std::string comment); void PrintComment(google::protobuf::io::Printer* printer, std::string comment);
// make a string of spaces as long as input // 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. // 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.). // 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 // 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); ...@@ -148,23 +148,19 @@ const char* PrimitiveTypeName(google::protobuf::FieldDescriptor::CppType type);
const char* DeclaredTypeMethodName(google::protobuf::FieldDescriptor::Type type); const char* DeclaredTypeMethodName(google::protobuf::FieldDescriptor::Type type);
// Convert a file name into a valid identifier. // Convert a file name into a valid identifier.
std::string FilenameIdentifier(const std::string& filename); std::string FilenameIdentifier(compat::StringView filename);
// Return the name of the BuildDescriptors() function for a given file.
std::string GlobalBuildDescriptorsName(const std::string& filename);
// return 'required', 'optional', or 'repeated' // return 'required', 'optional', or 'repeated'
std::string GetLabelName(google::protobuf::FieldDescriptor::Label label); std::string GetLabelName(google::protobuf::FieldDescriptor::Label label);
// write IntRanges entries for a bunch of sorted values. // write IntRanges entries for a bunch of sorted values.
// returns the number of ranges there are to bsearch. // 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 struct NameIndex
{ {
unsigned index; unsigned index;
const char *name; compat::StringView name;
}; };
int compare_name_indices_by_name(const void*, const void*); int compare_name_indices_by_name(const void*, const void*);
...@@ -186,16 +182,6 @@ inline int FieldSyntax(const google::protobuf::FieldDescriptor* field) { ...@@ -186,16 +182,6 @@ inline int FieldSyntax(const google::protobuf::FieldDescriptor* field) {
return 2; 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 } // namespace protobuf_c
#endif // PROTOBUF_C_PROTOC_GEN_C_C_HELPERS_H__ #endif // PROTOBUF_C_PROTOC_GEN_C_C_HELPERS_H__
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
#include "c_extension.h" #include "c_extension.h"
#include "c_helpers.h" #include "c_helpers.h"
#include "c_message.h" #include "c_message.h"
#include "compat.h"
namespace protobuf_c { namespace protobuf_c {
...@@ -460,203 +461,196 @@ GenerateHelperFunctionDefinitions(google::protobuf::io::Printer* printer, ...@@ -460,203 +461,196 @@ GenerateHelperFunctionDefinitions(google::protobuf::io::Printer* printer,
void MessageGenerator:: void MessageGenerator::
GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init) { GenerateMessageDescriptor(google::protobuf::io::Printer* printer, bool gen_init) {
std::map<std::string, std::string> vars; std::map<std::string, std::string> vars;
vars["fullname"] = descriptor_->full_name(); vars["fullname"] = descriptor_->full_name();
vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file()); vars["classname"] = FullNameToC(descriptor_->full_name(), descriptor_->file());
vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file()); vars["lcclassname"] = FullNameToLower(descriptor_->full_name(), descriptor_->file());
vars["shortname"] = ToCamel(descriptor_->name()); vars["shortname"] = ToCamel(descriptor_->name());
vars["n_fields"] = SimpleItoa(descriptor_->field_count()); vars["n_fields"] = SimpleItoa(descriptor_->field_count());
vars["packagename"] = descriptor_->file()->package(); vars["packagename"] = descriptor_->file()->package();
bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
descriptor_->file()->options().optimize_for() ==
google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
const ProtobufCMessageOptions opt =
descriptor_->options().GetExtension(pb_c_msg);
// Override parent settings, if needed
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);
}
for (int i = 0; i < descriptor_->enum_type_count(); i++) { bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
enum_generators_[i]->GenerateEnumDescriptor(printer); descriptor_->file()->options().optimize_for() ==
} google::protobuf::FileOptions_OptimizeMode_CODE_SIZE;
for (int i = 0; i < descriptor_->field_count(); i++) { const ProtobufCMessageOptions opt = descriptor_->options().GetExtension(pb_c_msg);
const google::protobuf::FieldDescriptor* fd = descriptor_->field(i); // Override parent settings, if needed
if (fd->has_default_value()) { if (opt.has_gen_init_helpers()) {
field_generators_.get(fd).GenerateDefaultValueImplementations(printer); gen_init = opt.gen_init_helpers();
} }
}
for (int i = 0; i < descriptor_->field_count(); i++) { for (int i = 0; i < descriptor_->nested_type_count(); i++) {
const google::protobuf::FieldDescriptor* fd = descriptor_->field(i); nested_generators_[i]->GenerateMessageDescriptor(printer, gen_init);
const ProtobufCFieldOptions opt = fd->options().GetExtension(pb_c_field); }
if (fd->has_default_value()) {
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
bool already_defined = false; enum_generators_[i]->GenerateEnumDescriptor(printer);
vars["name"] = fd->name(); }
vars["lcname"] = CamelToLower(fd->name());
vars["maybe_static"] = "static ";
vars["field_dv_ctype_suffix"] = "";
vars["default_value"] = field_generators_.get(fd).GetDefaultValue();
switch (fd->cpp_type()) {
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
vars["field_dv_ctype"] = "int32_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
vars["field_dv_ctype"] = "int64_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
vars["field_dv_ctype"] = "uint32_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
vars["field_dv_ctype"] = "uint64_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
vars["field_dv_ctype"] = "float";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
vars["field_dv_ctype"] = "double";
break;
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"] = "";
vars["field_dv_ctype"] = "{ ... }";
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())
{
vars["field_dv_ctype"] = "ProtobufCBinaryData";
}
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:
{
const google::protobuf::EnumValueDescriptor* vd = fd->default_value_enum();
vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name(), vd->type()->file());
break;
}
default:
GOOGLE_LOG(FATAL) << "Unknown CPPTYPE";
break;
}
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() ) {
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()];
for (int i = 0; i < descriptor_->field_count(); i++) { for (int i = 0; i < descriptor_->field_count(); i++) {
sorted_fields[i] = descriptor_->field(i); const google::protobuf::FieldDescriptor* fd = descriptor_->field(i);
if (fd->has_default_value()) {
field_generators_.get(fd).GenerateDefaultValueImplementations(printer);
}
} }
qsort (sorted_fields, descriptor_->field_count(),
sizeof(const google::protobuf::FieldDescriptor*),
compare_pfields_by_number);
for (int i = 0; i < descriptor_->field_count(); i++) { for (int i = 0; i < descriptor_->field_count(); i++) {
const google::protobuf::FieldDescriptor* field = sorted_fields[i]; const google::protobuf::FieldDescriptor* fd = descriptor_->field(i);
field_generators_.get(field).GenerateDescriptorInitializer(printer); 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());
vars["maybe_static"] = "static ";
vars["field_dv_ctype_suffix"] = "";
vars["default_value"] = field_generators_.get(fd).GetDefaultValue();
switch (fd->cpp_type()) {
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
vars["field_dv_ctype"] = "int32_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
vars["field_dv_ctype"] = "int64_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
vars["field_dv_ctype"] = "uint32_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
vars["field_dv_ctype"] = "uint64_t";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
vars["field_dv_ctype"] = "float";
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
vars["field_dv_ctype"] = "double";
break;
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"] = "";
vars["field_dv_ctype"] = "{ ... }";
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()) {
vars["field_dv_ctype"] = "ProtobufCBinaryData";
} 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: {
const google::protobuf::EnumValueDescriptor* vd = fd->default_value_enum();
vars["field_dv_ctype"] = FullNameToC(vd->type()->full_name(), vd->type()->file());
break;
}
default:
GOOGLE_LOG(FATAL) << "Unknown CPPTYPE";
break;
}
if (!already_defined) {
printer->Print(vars, "$maybe_static$const $field_dv_ctype$ $lcclassname$__$lcname$__default_value$field_dv_ctype_suffix$ = $default_value$;\n");
}
}
} }
printer->Outdent();
printer->Print(vars, "};\n");
if (!optimize_code_size) { if (descriptor_->field_count()) {
NameIndex *field_indices = new NameIndex [descriptor_->field_count()]; printer->Print(vars,
"static const ProtobufCFieldDescriptor $lcclassname$__field_descriptors[$n_fields$] =\n"
"{\n");
printer->Indent();
std::vector<const google::protobuf::FieldDescriptor*> sorted_fields;
for (int i = 0; i < descriptor_->field_count(); i++) { for (int i = 0; i < descriptor_->field_count(); i++) {
field_indices[i].name = sorted_fields[i]->name().c_str(); sorted_fields.push_back(descriptor_->field(i));
field_indices[i].index = i;
} }
qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex), qsort(&sorted_fields[0],
compare_name_indices_by_name); sorted_fields.size(),
printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n"); sizeof(const google::protobuf::FieldDescriptor*),
for (int i = 0; i < descriptor_->field_count(); i++) { compare_pfields_by_number);
vars["index"] = SimpleItoa(field_indices[i].index); for (auto field : sorted_fields) {
vars["name"] = field_indices[i].name; field_generators_.get(field).GenerateDescriptorInitializer(printer);
printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
} }
printer->Print("};\n"); printer->Outdent();
delete[] field_indices; printer->Print(vars, "};\n");
}
// create range initializers if (!optimize_code_size) {
int *values = new int[descriptor_->field_count()]; std::vector<NameIndex> field_indices;
for (int i = 0; i < descriptor_->field_count(); i++) { for (unsigned i = 0; i < descriptor_->field_count(); i++) {
values[i] = sorted_fields[i]->number(); field_indices.push_back({ i, sorted_fields[i]->name() });
} }
int n_ranges = WriteIntRanges(printer, qsort(&field_indices[0],
descriptor_->field_count(), values, field_indices.size(),
vars["lcclassname"] + "__number_ranges"); sizeof(NameIndex),
delete [] values; compare_name_indices_by_name);
delete [] sorted_fields; printer->Print(vars, "static const unsigned $lcclassname$__field_indices_by_name[] = {\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
vars["index"] = SimpleItoa(field_indices[i].index);
vars["name"] = field_indices[i].name;
printer->Print(vars, " $index$, /* field[$index$] = $name$ */\n");
}
printer->Print("};\n");
}
vars["n_ranges"] = SimpleItoa(n_ranges); // create range initializers
} else { std::vector<int> values;
/* MS compiler can't handle arrays with zero size and empty for (int i = 0; i < descriptor_->field_count(); i++) {
* initialization list. Furthermore it is an extension of GCC only but values.push_back(sorted_fields[i]->number());
* not a standard. */
vars["n_ranges"] = "0";
printer->Print(vars,
"#define $lcclassname$__field_descriptors NULL\n"
"#define $lcclassname$__field_indices_by_name NULL\n"
"#define $lcclassname$__number_ranges NULL\n");
} }
int n_ranges = WriteIntRanges(printer,
descriptor_->field_count(),
&values[0],
vars["lcclassname"] + "__number_ranges");
vars["n_ranges"] = SimpleItoa(n_ranges);
} else {
/* MS compiler can't handle arrays with zero size and empty
* initialization list. Furthermore it is an extension of GCC only but
* not a standard. */
vars["n_ranges"] = "0";
printer->Print(vars,
"#define $lcclassname$__field_descriptors NULL\n"
"#define $lcclassname$__field_indices_by_name NULL\n"
"#define $lcclassname$__number_ranges NULL\n");
}
printer->Print(vars, printer->Print(vars,
"const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n" "const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n"
"{\n" "{\n"
" PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n"); " PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n");
if (optimize_code_size) { if (optimize_code_size) {
printer->Print(" NULL,NULL,NULL,NULL, /* CODE_SIZE */\n"); printer->Print(" NULL,NULL,NULL,NULL, /* CODE_SIZE */\n");
} else { } else {
printer->Print(vars, printer->Print(vars,
" \"$fullname$\",\n" " \"$fullname$\",\n"
" \"$shortname$\",\n" " \"$shortname$\",\n"
" \"$classname$\",\n" " \"$classname$\",\n"
" \"$packagename$\",\n"); " \"$packagename$\",\n");
} }
printer->Print(vars, printer->Print(vars,
" sizeof($classname$),\n" " sizeof($classname$),\n"
" $n_fields$,\n" " $n_fields$,\n"
" $lcclassname$__field_descriptors,\n"); " $lcclassname$__field_descriptors,\n");
if (optimize_code_size) { if (optimize_code_size) {
printer->Print(" NULL, /* CODE_SIZE */\n"); printer->Print(" NULL, /* CODE_SIZE */\n");
} else { } else {
printer->Print(vars, printer->Print(vars, " $lcclassname$__field_indices_by_name,\n");
" $lcclassname$__field_indices_by_name,\n");
} }
printer->Print(vars, printer->Print(vars,
" $n_ranges$," " $n_ranges$,"
" $lcclassname$__number_ranges,\n"); " $lcclassname$__number_ranges,\n");
if (gen_init) { if (gen_init) {
printer->Print(vars, printer->Print(vars, " (ProtobufCMessageInit) $lcclassname$__init,\n");
" (ProtobufCMessageInit) $lcclassname$__init,\n");
} else { } else {
printer->Print(vars, printer->Print(vars, " NULL, /* gen_init_helpers = false */\n");
" NULL, /* gen_init_helpers = false */\n");
} }
printer->Print(vars, printer->Print(vars,
" NULL,NULL,NULL /* reserved[123] */\n" " NULL,NULL,NULL /* reserved[123] */\n"
"};\n"); "};\n");
} }
int MessageGenerator::GetOneofUnionOrder(const google::protobuf::FieldDescriptor* fd) int MessageGenerator::GetOneofUnionOrder(const google::protobuf::FieldDescriptor* fd)
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
#include "c_helpers.h" #include "c_helpers.h"
#include "c_primitive_field.h" #include "c_primitive_field.h"
#include "compat.h"
namespace protobuf_c { namespace protobuf_c {
......
...@@ -184,19 +184,19 @@ void ServiceGenerator::GenerateInit(google::protobuf::io::Printer* printer) ...@@ -184,19 +184,19 @@ void ServiceGenerator::GenerateInit(google::protobuf::io::Printer* printer)
"}\n"); "}\n");
} }
struct MethodIndexAndName { unsigned i; const char *name; }; struct MethodIndexAndName { unsigned i; compat::StringView name; };
static int static int
compare_method_index_and_name_by_name (const void *a, const void *b) compare_method_index_and_name_by_name (const void *a, const void *b)
{ {
const MethodIndexAndName *ma = (const MethodIndexAndName *) a; const MethodIndexAndName *ma = (const MethodIndexAndName *) a;
const MethodIndexAndName *mb = (const MethodIndexAndName *) b; 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) void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer* printer)
{ {
int n_methods = descriptor_->method_count(); 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() && bool optimize_code_size = descriptor_->file()->options().has_optimize_for() &&
descriptor_->file()->options().optimize_for() == descriptor_->file()->options().optimize_for() ==
...@@ -205,7 +205,7 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer* ...@@ -205,7 +205,7 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
vars_["n_methods"] = SimpleItoa(n_methods); vars_["n_methods"] = SimpleItoa(n_methods);
printer->Print(vars_, "static const ProtobufCMethodDescriptor $lcfullname$__method_descriptors[$n_methods$] =\n" printer->Print(vars_, "static const ProtobufCMethodDescriptor $lcfullname$__method_descriptors[$n_methods$] =\n"
"{\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); const google::protobuf::MethodDescriptor* method = descriptor_->method(i);
vars_["method"] = method->name(); vars_["method"] = method->name();
vars_["input_descriptor"] = "&" + FullNameToLower(method->input_type()->full_name(), method->input_type()->file()) + "__descriptor"; vars_["input_descriptor"] = "&" + FullNameToLower(method->input_type()->full_name(), method->input_type()->file()) + "__descriptor";
...@@ -217,14 +217,15 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer* ...@@ -217,14 +217,15 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
printer->Print(vars_, printer->Print(vars_,
" { \"$method$\", $input_descriptor$, $output_descriptor$ },\n"); " { \"$method$\", $input_descriptor$, $output_descriptor$ },\n");
} }
mi_array[i].i = i; mi_array.push_back({i, method->name()});
mi_array[i].name = method->name().c_str();
} }
printer->Print(vars_, "};\n"); printer->Print(vars_, "};\n");
if (!optimize_code_size) { if (!optimize_code_size) {
qsort ((void*)mi_array, n_methods, sizeof (MethodIndexAndName), qsort(&mi_array[0],
compare_method_index_and_name_by_name); mi_array.size(),
sizeof(MethodIndexAndName),
compare_method_index_and_name_by_name);
printer->Print(vars_, "const unsigned $lcfullname$__method_indices_by_name[] = {\n"); printer->Print(vars_, "const unsigned $lcfullname$__method_indices_by_name[] = {\n");
for (int i = 0; i < n_methods; i++) { for (int i = 0; i < n_methods; i++) {
vars_["i"] = SimpleItoa(mi_array[i].i); vars_["i"] = SimpleItoa(mi_array[i].i);
...@@ -258,8 +259,6 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer* ...@@ -258,8 +259,6 @@ void ServiceGenerator::GenerateServiceDescriptor(google::protobuf::io::Printer*
" $lcfullname$__method_indices_by_name\n" " $lcfullname$__method_indices_by_name\n"
"};\n"); "};\n");
} }
delete[] mi_array;
} }
void ServiceGenerator::GenerateCallersImplementations(google::protobuf::io::Printer* printer) 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 @@ ...@@ -32,6 +32,7 @@
#include "c_generator.h" #include "c_generator.h"
#include "c_helpers.h" #include "c_helpers.h"
#include "compat.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
protobuf_c::CGenerator c_generator; 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