From f486c8ed66b70d559c5f3a5e43c09302f4b2211e Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Sun, 21 Mar 2021 16:08:51 -0700 Subject: [PATCH] protoc-c: add use_oneof_field_name option Allows for generic oneof offset lookups based on the name of the oneof, instead of having to know the field name. All oneof fields should have the same offset, since they are members of a union. Fixes #204 --- Makefile.am | 17 +++++++++++++ protobuf-c/protobuf-c.proto | 4 ++++ protoc-c/c_field.cc | 8 +++++-- t/issue204/.gitignore | 1 + t/issue204/issue204.c | 48 +++++++++++++++++++++++++++++++++++++ t/issue204/issue204.proto | 15 ++++++++++++ 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 t/issue204/.gitignore create mode 100644 t/issue204/issue204.c create mode 100644 t/issue204/issue204.proto diff --git a/Makefile.am b/Makefile.am index 1e1e1df..2efc11e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -226,6 +226,23 @@ t_version_version_SOURCES = \ t_version_version_LDADD = \ protobuf-c/libprotobuf-c.la +# Issue #204 +check_PROGRAMS += \ + t/issue204/issue204 +TESTS += \ + t/issue204/issue204 +t_issue204_issue204_SOURCES = \ + t/issue204/issue204.c \ + t/issue204/issue204.pb-c.c +t_issue204_issue204_LDADD = \ + protobuf-c/libprotobuf-c.la +t/issue204/issue204.pb-c.c t/issue204/issue204.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/issue204/issue204.proto + $(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/issue204/issue204.proto +BUILT_SOURCES += \ + t/issue204/issue204.pb-c.c t/issue204/issue204.pb-c.h +EXTRA_DIST += \ + t/issue204/issue204.proto + # Issue #220 check_PROGRAMS += \ t/issue220/issue220 diff --git a/protobuf-c/protobuf-c.proto b/protobuf-c/protobuf-c.proto index 644f851..1da934f 100644 --- a/protobuf-c/protobuf-c.proto +++ b/protobuf-c/protobuf-c.proto @@ -48,6 +48,10 @@ message ProtobufCFileOptions { // Use const char * instead of char * for string fields optional bool const_strings = 4 [default = false]; + + // For oneof fields, set ProtobufCFieldDescriptor name field to the + // name of the containing oneof, instead of the field name + optional bool use_oneof_field_name = 5 [default = false]; } extend google.protobuf.FileOptions { diff --git a/protoc-c/c_field.cc b/protoc-c/c_field.cc index 597bf03..8eda7d2 100644 --- a/protoc-c/c_field.cc +++ b/protoc-c/c_field.cc @@ -107,13 +107,17 @@ void FieldGenerator::GenerateDescriptorInitializerGeneric(io::Printer* printer, const std::string &descriptor_addr) const { std::map variables; + const OneofDescriptor *oneof = descriptor_->containing_oneof(); + const ProtobufCFileOptions opt = descriptor_->file()->options().GetExtension(pb_c_file); variables["TYPE"] = type_macro; variables["classname"] = FullNameToC(FieldScope(descriptor_)->full_name()); variables["name"] = FieldName(descriptor_); - variables["proto_name"] = descriptor_->name(); + if (opt.use_oneof_field_name()) + variables["proto_name"] = oneof->name(); + else + variables["proto_name"] = descriptor_->name(); variables["descriptor_addr"] = descriptor_addr; variables["value"] = SimpleItoa(descriptor_->number()); - const OneofDescriptor *oneof = descriptor_->containing_oneof(); if (oneof != NULL) variables["oneofname"] = FullNameToLower(oneof->name()); diff --git a/t/issue204/.gitignore b/t/issue204/.gitignore new file mode 100644 index 0000000..5c03b12 --- /dev/null +++ b/t/issue204/.gitignore @@ -0,0 +1 @@ +issue204 diff --git a/t/issue204/issue204.c b/t/issue204/issue204.c new file mode 100644 index 0000000..01a321a --- /dev/null +++ b/t/issue204/issue204.c @@ -0,0 +1,48 @@ +#include + +#include "t/issue251/issue251.pb-c.h" + +int main(void) +{ + TwoOneofs msg = TWO_ONEOFS__INIT; + const ProtobufCFieldDescriptor *field; + unsigned off1, off2, off_name; + field = protobuf_c_message_descriptor_get_field_by_name( + msg.base.descriptor, + "first_oneof"); + assert (field); + off_name = field->offset; + field = protobuf_c_message_descriptor_get_field( + msg.base.descriptor, + 10); + assert (field); + off1 = field->offset; + field = protobuf_c_message_descriptor_get_field( + msg.base.descriptor, + 11); + assert (field); + off2 = field->offset; + + assert (off_name == off1); + assert (off1 == off2); + + field = protobuf_c_message_descriptor_get_field_by_name( + msg.base.descriptor, + "second_oneof"); + assert (field); + off_name = field->offset; + field = protobuf_c_message_descriptor_get_field( + msg.base.descriptor, + 20); + assert (field); + off1 = field->offset; + field = protobuf_c_message_descriptor_get_field( + msg.base.descriptor, + 21); + assert (field); + off2 = field->offset; + + assert (off_name == off1); + assert (off1 == off2); + return EXIT_SUCCESS; +} diff --git a/t/issue204/issue204.proto b/t/issue204/issue204.proto new file mode 100644 index 0000000..6934570 --- /dev/null +++ b/t/issue204/issue204.proto @@ -0,0 +1,15 @@ +import "protobuf-c/protobuf-c.proto"; + +option (pb_c_file).use_oneof_field_name = true; + +message two_oneofs { + oneof first_oneof { + bool a = 10; + bool b = 11; + } + + oneof second_oneof { + bool c = 20; + bool d = 21; + } +}