mirror of
https://github.com/protobuf-c/protobuf-c.git
synced 2024-12-27 13:31:02 +08:00
protoc-c: add options for function generation
Add options controller helper function generation. Preserve existing behavior of not generating pack/unpack functions for sub-messages if option is not explicitly set. Fixes #240 Fixes #442
This commit is contained in:
parent
883b1acc1b
commit
baa860ff97
@ -37,6 +37,14 @@ option (pb_c_file).no_generate = true;
|
||||
message ProtobufCFileOptions {
|
||||
// Suppresses pb-c.{c,h} file output completely.
|
||||
optional bool no_generate = 1 [default = false];
|
||||
|
||||
// Generate helper pack/unpack functions?
|
||||
// For backwards compatibility, if this field is not explicitly set,
|
||||
// only top-level message pack/unpack functions will be generated
|
||||
optional bool gen_pack_helpers = 2 [default = true];
|
||||
|
||||
// Generate helper init message functions?
|
||||
optional bool gen_init_helpers = 3 [default = true];
|
||||
}
|
||||
|
||||
extend google.protobuf.FileOptions {
|
||||
@ -44,6 +52,11 @@ extend google.protobuf.FileOptions {
|
||||
}
|
||||
|
||||
message ProtobufCMessageOptions {
|
||||
// Overrides the parent setting only if present
|
||||
optional bool gen_pack_helpers = 1 [default = false];
|
||||
|
||||
// Overrides the parent setting only if present
|
||||
optional bool gen_init_helpers = 2 [default = true];
|
||||
}
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
|
@ -191,7 +191,13 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateHelperFunctionDeclarations(printer, false);
|
||||
const ProtobufCFileOptions opt = file_->options().GetExtension(pb_c_file);
|
||||
|
||||
message_generators_[i]->GenerateHelperFunctionDeclarations(
|
||||
printer,
|
||||
opt.has_gen_pack_helpers(),
|
||||
opt.gen_pack_helpers(),
|
||||
opt.gen_init_helpers());
|
||||
}
|
||||
|
||||
printer->Print("/* --- per-message closures --- */\n\n");
|
||||
@ -265,11 +271,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||
}
|
||||
#endif
|
||||
|
||||
const ProtobufCFileOptions opt = file_->options().GetExtension(pb_c_file);
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateHelperFunctionDefinitions(printer, false);
|
||||
message_generators_[i]->GenerateHelperFunctionDefinitions(
|
||||
printer,
|
||||
opt.has_gen_pack_helpers(),
|
||||
opt.gen_pack_helpers(),
|
||||
opt.gen_init_helpers());
|
||||
}
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateMessageDescriptor(printer);
|
||||
message_generators_[i]->GenerateMessageDescriptor(printer,
|
||||
opt.gen_init_helpers());
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateEnumDescriptor(printer);
|
||||
|
@ -252,21 +252,38 @@ GenerateStructDefinition(io::Printer* printer) {
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateHelperFunctionDeclarations(io::Printer* printer, bool is_submessage)
|
||||
GenerateHelperFunctionDeclarations(io::Printer* printer,
|
||||
bool is_pack_deep,
|
||||
bool gen_pack,
|
||||
bool gen_init)
|
||||
{
|
||||
const ProtobufCMessageOptions opt =
|
||||
descriptor_->options().GetExtension(pb_c_msg);
|
||||
|
||||
// Override parent settings, if needed
|
||||
if (opt.has_gen_pack_helpers())
|
||||
gen_pack = opt.gen_pack_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]->GenerateHelperFunctionDeclarations(printer, true);
|
||||
bool nested_pack = !is_pack_deep ? opt.gen_pack_helpers() : gen_pack;
|
||||
nested_generators_[i]->GenerateHelperFunctionDeclarations(printer, true,
|
||||
nested_pack,
|
||||
gen_init);
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> vars;
|
||||
vars["classname"] = FullNameToC(descriptor_->full_name());
|
||||
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
||||
if (gen_init) {
|
||||
printer->Print(vars,
|
||||
"/* $classname$ methods */\n"
|
||||
"void $lcclassname$__init\n"
|
||||
" ($classname$ *message);\n"
|
||||
);
|
||||
if (!is_submessage) {
|
||||
}
|
||||
if (gen_pack) {
|
||||
printer->Print(vars,
|
||||
"size_t $lcclassname$__get_packed_size\n"
|
||||
" (const $classname$ *message);\n"
|
||||
@ -325,16 +342,32 @@ compare_pfields_by_number (const void *a, const void *b)
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateHelperFunctionDefinitions(io::Printer* printer, bool is_submessage)
|
||||
GenerateHelperFunctionDefinitions(io::Printer* printer,
|
||||
bool is_pack_deep,
|
||||
bool gen_pack,
|
||||
bool gen_init)
|
||||
{
|
||||
const ProtobufCMessageOptions opt =
|
||||
descriptor_->options().GetExtension(pb_c_msg);
|
||||
|
||||
// Override parent settings, if needed
|
||||
if (opt.has_gen_pack_helpers())
|
||||
gen_pack = opt.gen_pack_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]->GenerateHelperFunctionDefinitions(printer, true);
|
||||
bool nested_pack = !is_pack_deep ? opt.gen_pack_helpers() : gen_pack;
|
||||
nested_generators_[i]->GenerateHelperFunctionDefinitions(printer, true,
|
||||
nested_pack,
|
||||
gen_init);
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> vars;
|
||||
vars["classname"] = FullNameToC(descriptor_->full_name());
|
||||
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
||||
vars["ucclassname"] = FullNameToUpper(descriptor_->full_name());
|
||||
if (gen_init) {
|
||||
printer->Print(vars,
|
||||
"void $lcclassname$__init\n"
|
||||
" ($classname$ *message)\n"
|
||||
@ -342,7 +375,8 @@ GenerateHelperFunctionDefinitions(io::Printer* printer, bool is_submessage)
|
||||
" static const $classname$ init_value = $ucclassname$__INIT;\n"
|
||||
" *message = init_value;\n"
|
||||
"}\n");
|
||||
if (!is_submessage) {
|
||||
}
|
||||
if (gen_pack) {
|
||||
printer->Print(vars,
|
||||
"size_t $lcclassname$__get_packed_size\n"
|
||||
" (const $classname$ *message)\n"
|
||||
@ -388,7 +422,7 @@ GenerateHelperFunctionDefinitions(io::Printer* printer, bool is_submessage)
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateMessageDescriptor(io::Printer* printer) {
|
||||
GenerateMessageDescriptor(io::Printer* printer, bool gen_init) {
|
||||
std::map<std::string, std::string> vars;
|
||||
vars["fullname"] = descriptor_->full_name();
|
||||
vars["classname"] = FullNameToC(descriptor_->full_name());
|
||||
@ -401,8 +435,14 @@ GenerateMessageDescriptor(io::Printer* printer) {
|
||||
descriptor_->file()->options().optimize_for() ==
|
||||
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);
|
||||
nested_generators_[i]->GenerateMessageDescriptor(printer, gen_init);
|
||||
}
|
||||
|
||||
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
||||
@ -568,8 +608,15 @@ GenerateMessageDescriptor(io::Printer* printer) {
|
||||
}
|
||||
printer->Print(vars,
|
||||
" $n_ranges$,"
|
||||
" $lcclassname$__number_ranges,\n"
|
||||
" (ProtobufCMessageInit) $lcclassname$__init,\n"
|
||||
" $lcclassname$__number_ranges,\n");
|
||||
if (gen_init) {
|
||||
printer->Print(vars,
|
||||
" (ProtobufCMessageInit) $lcclassname$__init,\n");
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
" NULL, /* gen_init_helpers = false */\n");
|
||||
}
|
||||
printer->Print(vars,
|
||||
" NULL,NULL,NULL /* reserved[123] */\n"
|
||||
"};\n");
|
||||
}
|
||||
|
@ -111,14 +111,20 @@ class MessageGenerator {
|
||||
void GenerateStructStaticInitMacro(io::Printer* printer);
|
||||
|
||||
// Generate standard helper functions declarations for this message.
|
||||
void GenerateHelperFunctionDeclarations(io::Printer* printer, bool is_submessage);
|
||||
void GenerateHelperFunctionDeclarations(io::Printer* printer,
|
||||
bool is_pack_deep,
|
||||
bool gen_pack,
|
||||
bool gen_init);
|
||||
|
||||
// Source file stuff.
|
||||
|
||||
// Generate code that initializes the global variable storing the message's
|
||||
// descriptor.
|
||||
void GenerateMessageDescriptor(io::Printer* printer);
|
||||
void GenerateHelperFunctionDefinitions(io::Printer* printer, bool is_submessage);
|
||||
void GenerateMessageDescriptor(io::Printer* printer, bool gen_init);
|
||||
void GenerateHelperFunctionDefinitions(io::Printer* printer,
|
||||
bool is_pack_deep,
|
||||
bool gen_pack,
|
||||
bool gen_init);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -432,6 +432,39 @@ static void test_required_SubMess (void)
|
||||
#undef DO_TEST
|
||||
}
|
||||
|
||||
static size_t foo__test_mess_optional__get_packed_size
|
||||
(const Foo__TestMessOptional *message)
|
||||
{
|
||||
assert(message->base.descriptor == &foo__test_mess_optional__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
static size_t foo__test_mess_optional__pack
|
||||
(const Foo__TestMessOptional *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &foo__test_mess_optional__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
static Foo__TestMessOptional *
|
||||
foo__test_mess_optional__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (Foo__TestMessOptional *)
|
||||
protobuf_c_message_unpack (&foo__test_mess_optional__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
static void foo__test_mess_optional__free_unpacked
|
||||
(Foo__TestMessOptional *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &foo__test_mess_optional__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
|
||||
/* === Optional type fields === */
|
||||
static void test_empty_optional (void)
|
||||
{
|
||||
|
@ -117,6 +117,8 @@ message TestMessPacked {
|
||||
}
|
||||
|
||||
message TestMessOptional {
|
||||
option (pb_c_msg).gen_pack_helpers = false;
|
||||
option (pb_c_msg).gen_init_helpers = false;
|
||||
optional int32 test_int32 = 1;
|
||||
optional sint32 test_sint32 = 2;
|
||||
optional sfixed32 test_sfixed32 = 3;
|
||||
|
Loading…
x
Reference in New Issue
Block a user