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 {
|
message ProtobufCFileOptions {
|
||||||
// Suppresses pb-c.{c,h} file output completely.
|
// Suppresses pb-c.{c,h} file output completely.
|
||||||
optional bool no_generate = 1 [default = false];
|
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 {
|
extend google.protobuf.FileOptions {
|
||||||
@ -44,6 +52,11 @@ extend google.protobuf.FileOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ProtobufCMessageOptions {
|
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 {
|
extend google.protobuf.MessageOptions {
|
||||||
|
@ -191,7 +191,13 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
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");
|
printer->Print("/* --- per-message closures --- */\n\n");
|
||||||
@ -265,11 +271,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const ProtobufCFileOptions opt = file_->options().GetExtension(pb_c_file);
|
||||||
|
|
||||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
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++) {
|
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++) {
|
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||||
enum_generators_[i]->GenerateEnumDescriptor(printer);
|
enum_generators_[i]->GenerateEnumDescriptor(printer);
|
||||||
|
@ -252,21 +252,38 @@ GenerateStructDefinition(io::Printer* printer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessageGenerator::
|
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++) {
|
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;
|
std::map<std::string, std::string> vars;
|
||||||
vars["classname"] = FullNameToC(descriptor_->full_name());
|
vars["classname"] = FullNameToC(descriptor_->full_name());
|
||||||
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
||||||
printer->Print(vars,
|
if (gen_init) {
|
||||||
|
printer->Print(vars,
|
||||||
"/* $classname$ methods */\n"
|
"/* $classname$ methods */\n"
|
||||||
"void $lcclassname$__init\n"
|
"void $lcclassname$__init\n"
|
||||||
" ($classname$ *message);\n"
|
" ($classname$ *message);\n"
|
||||||
);
|
);
|
||||||
if (!is_submessage) {
|
}
|
||||||
|
if (gen_pack) {
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"size_t $lcclassname$__get_packed_size\n"
|
"size_t $lcclassname$__get_packed_size\n"
|
||||||
" (const $classname$ *message);\n"
|
" (const $classname$ *message);\n"
|
||||||
@ -325,24 +342,41 @@ compare_pfields_by_number (const void *a, const void *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessageGenerator::
|
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++) {
|
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;
|
std::map<std::string, std::string> vars;
|
||||||
vars["classname"] = FullNameToC(descriptor_->full_name());
|
vars["classname"] = FullNameToC(descriptor_->full_name());
|
||||||
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
||||||
vars["ucclassname"] = FullNameToUpper(descriptor_->full_name());
|
vars["ucclassname"] = FullNameToUpper(descriptor_->full_name());
|
||||||
printer->Print(vars,
|
if (gen_init) {
|
||||||
|
printer->Print(vars,
|
||||||
"void $lcclassname$__init\n"
|
"void $lcclassname$__init\n"
|
||||||
" ($classname$ *message)\n"
|
" ($classname$ *message)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" static const $classname$ init_value = $ucclassname$__INIT;\n"
|
" static const $classname$ init_value = $ucclassname$__INIT;\n"
|
||||||
" *message = init_value;\n"
|
" *message = init_value;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
if (!is_submessage) {
|
}
|
||||||
|
if (gen_pack) {
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
"size_t $lcclassname$__get_packed_size\n"
|
"size_t $lcclassname$__get_packed_size\n"
|
||||||
" (const $classname$ *message)\n"
|
" (const $classname$ *message)\n"
|
||||||
@ -388,7 +422,7 @@ GenerateHelperFunctionDefinitions(io::Printer* printer, bool is_submessage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessageGenerator::
|
void MessageGenerator::
|
||||||
GenerateMessageDescriptor(io::Printer* printer) {
|
GenerateMessageDescriptor(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());
|
vars["classname"] = FullNameToC(descriptor_->full_name());
|
||||||
@ -401,8 +435,14 @@ GenerateMessageDescriptor(io::Printer* printer) {
|
|||||||
descriptor_->file()->options().optimize_for() ==
|
descriptor_->file()->options().optimize_for() ==
|
||||||
FileOptions_OptimizeMode_CODE_SIZE;
|
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++) {
|
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++) {
|
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
||||||
@ -568,8 +608,15 @@ GenerateMessageDescriptor(io::Printer* printer) {
|
|||||||
}
|
}
|
||||||
printer->Print(vars,
|
printer->Print(vars,
|
||||||
" $n_ranges$,"
|
" $n_ranges$,"
|
||||||
" $lcclassname$__number_ranges,\n"
|
" $lcclassname$__number_ranges,\n");
|
||||||
" (ProtobufCMessageInit) $lcclassname$__init,\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"
|
" NULL,NULL,NULL /* reserved[123] */\n"
|
||||||
"};\n");
|
"};\n");
|
||||||
}
|
}
|
||||||
|
@ -111,14 +111,20 @@ class MessageGenerator {
|
|||||||
void GenerateStructStaticInitMacro(io::Printer* printer);
|
void GenerateStructStaticInitMacro(io::Printer* printer);
|
||||||
|
|
||||||
// Generate standard helper functions declarations for this message.
|
// 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.
|
// Source file stuff.
|
||||||
|
|
||||||
// Generate code that initializes the global variable storing the message's
|
// Generate code that initializes the global variable storing the message's
|
||||||
// descriptor.
|
// descriptor.
|
||||||
void GenerateMessageDescriptor(io::Printer* printer);
|
void GenerateMessageDescriptor(io::Printer* printer, bool gen_init);
|
||||||
void GenerateHelperFunctionDefinitions(io::Printer* printer, bool is_submessage);
|
void GenerateHelperFunctionDefinitions(io::Printer* printer,
|
||||||
|
bool is_pack_deep,
|
||||||
|
bool gen_pack,
|
||||||
|
bool gen_init);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -432,6 +432,39 @@ static void test_required_SubMess (void)
|
|||||||
#undef DO_TEST
|
#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 === */
|
/* === Optional type fields === */
|
||||||
static void test_empty_optional (void)
|
static void test_empty_optional (void)
|
||||||
{
|
{
|
||||||
|
@ -117,6 +117,8 @@ message TestMessPacked {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message TestMessOptional {
|
message TestMessOptional {
|
||||||
|
option (pb_c_msg).gen_pack_helpers = false;
|
||||||
|
option (pb_c_msg).gen_init_helpers = false;
|
||||||
optional int32 test_int32 = 1;
|
optional int32 test_int32 = 1;
|
||||||
optional sint32 test_sint32 = 2;
|
optional sint32 test_sint32 = 2;
|
||||||
optional sfixed32 test_sfixed32 = 3;
|
optional sfixed32 test_sfixed32 = 3;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user