diff --git a/protobuf-c/protobuf-c.proto b/protobuf-c/protobuf-c.proto index 66de032..48506f4 100644 --- a/protobuf-c/protobuf-c.proto +++ b/protobuf-c/protobuf-c.proto @@ -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 { diff --git a/protoc-c/c_file.cc b/protoc-c/c_file.cc index 9ea788b..54a5133 100644 --- a/protoc-c/c_file.cc +++ b/protoc-c/c_file.cc @@ -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); diff --git a/protoc-c/c_message.cc b/protoc-c/c_message.cc index 660129d..60c7c30 100755 --- a/protoc-c/c_message.cc +++ b/protoc-c/c_message.cc @@ -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 vars; vars["classname"] = FullNameToC(descriptor_->full_name()); vars["lcclassname"] = FullNameToLower(descriptor_->full_name()); - printer->Print(vars, + 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,24 +342,41 @@ 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 vars; vars["classname"] = FullNameToC(descriptor_->full_name()); vars["lcclassname"] = FullNameToLower(descriptor_->full_name()); vars["ucclassname"] = FullNameToUpper(descriptor_->full_name()); - printer->Print(vars, + if (gen_init) { + printer->Print(vars, "void $lcclassname$__init\n" " ($classname$ *message)\n" "{\n" " 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 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"); } diff --git a/protoc-c/c_message.h b/protoc-c/c_message.h index c5e8431..ea1c3ab 100644 --- a/protoc-c/c_message.h +++ b/protoc-c/c_message.h @@ -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: diff --git a/t/generated-code2/test-generated-code2.c b/t/generated-code2/test-generated-code2.c index e1e50bc..2aa3a9c 100755 --- a/t/generated-code2/test-generated-code2.c +++ b/t/generated-code2/test-generated-code2.c @@ -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) { diff --git a/t/test-full.proto b/t/test-full.proto index 2ebd690..f56fbf7 100644 --- a/t/test-full.proto +++ b/t/test-full.proto @@ -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;