From 603e431864d9b1dc24f31ef2d95cf119a4945bf1 Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Sat, 14 Feb 2015 17:17:10 -0800 Subject: [PATCH] protoc-c: Support the optimize_for = LITE_RUNTIME file option Adds support for the LITE_RUNTIME optimization option to the protobuf-c compiler. Enabling this option would generate lighter weight message, enum, and service descriptors that contain NO strings. As a result, calls to lookup descriptors via the *_get_{field,value,method}_by_name API will return NULL. Default compiler behavior (when optimize_for is not specified or is not set to LITE_RUNTIME) is unchanged. --- protoc-c/c_enum.cc | 129 +++++++++++++++++++++++++----------------- protoc-c/c_field.cc | 10 +++- protoc-c/c_message.cc | 80 ++++++++++++++++---------- protoc-c/c_service.cc | 69 ++++++++++++++-------- 4 files changed, 180 insertions(+), 108 deletions(-) diff --git a/protoc-c/c_enum.cc b/protoc-c/c_enum.cc index 29a8076..c4167ca 100644 --- a/protoc-c/c_enum.cc +++ b/protoc-c/c_enum.cc @@ -150,11 +150,17 @@ void EnumGenerator::GenerateValueInitializer(io::Printer *printer, int index) { const EnumValueDescriptor *vd = descriptor_->value(index); map vars; + bool lite_runtime = descriptor_->file()->options().has_optimize_for() && + descriptor_->file()->options().optimize_for() == + FileOptions_OptimizeMode_LITE_RUNTIME; vars["enum_value_name"] = vd->name(); vars["c_enum_value_name"] = FullNameToUpper(descriptor_->full_name()) + "__" + vd->name(); vars["value"] = SimpleItoa(vd->number()); - printer->Print(vars, - " { \"$enum_value_name$\", \"$c_enum_value_name$\", $value$ },\n"); + if (lite_runtime) + printer->Print(vars, " { NULL, NULL, $value$ }, /* LITE_RUNTIME */\n"); + else + printer->Print(vars, + " { \"$enum_value_name$\", \"$c_enum_value_name$\", $value$ },\n"); } static int compare_value_indices_by_value_then_index(const void *a, const void *b) @@ -184,6 +190,10 @@ void EnumGenerator::GenerateEnumDescriptor(io::Printer* printer) { vars["packagename"] = descriptor_->file()->package(); vars["value_count"] = SimpleItoa(descriptor_->value_count()); + bool lite_runtime = descriptor_->file()->options().has_optimize_for() && + descriptor_->file()->options().optimize_for() == + FileOptions_OptimizeMode_LITE_RUNTIME; + // Sort by name and value, dropping duplicate values if they appear later. // TODO: use a c++ paradigm for this! NameIndex *name_index = new NameIndex[descriptor_->value_count()]; @@ -216,13 +226,13 @@ void EnumGenerator::GenerateEnumDescriptor(io::Printer* printer) { vars["unique_value_count"] = SimpleItoa(n_unique_values); printer->Print(vars, - "static const ProtobufCEnumValue $lcclassname$__enum_values_by_number[$unique_value_count$] =\n" - "{\n"); + "static const ProtobufCEnumValue $lcclassname$__enum_values_by_number[$unique_value_count$] =\n" + "{\n"); if (descriptor_->value_count() > 0) { GenerateValueInitializer(printer, value_index[0].index); for (int j = 1; j < descriptor_->value_count(); j++) { if (value_index[j-1].value != value_index[j].value) { - GenerateValueInitializer(printer, value_index[j].index); + GenerateValueInitializer(printer, value_index[j].index); } } } @@ -236,64 +246,81 @@ void EnumGenerator::GenerateEnumDescriptor(io::Printer* printer) { int last_value = range_start_value; for (int j = 1; j < descriptor_->value_count(); j++) { if (value_index[j-1].value != value_index[j].value) { - if (last_value + 1 == value_index[j].value) { - range_len++; - } else { - // output range - vars["range_start_value"] = SimpleItoa(range_start_value); - vars["orig_index"] = SimpleItoa(range_start); - printer->Print (vars, "{$range_start_value$, $orig_index$},"); - range_start_value = value_index[j].value; - range_start += range_len; - range_len = 1; - n_ranges++; - } - last_value = value_index[j].value; + if (last_value + 1 == value_index[j].value) { + range_len++; + } else { + // output range + vars["range_start_value"] = SimpleItoa(range_start_value); + vars["orig_index"] = SimpleItoa(range_start); + printer->Print (vars, "{$range_start_value$, $orig_index$},"); + range_start_value = value_index[j].value; + range_start += range_len; + range_len = 1; + n_ranges++; + } + last_value = value_index[j].value; } } { - vars["range_start_value"] = SimpleItoa(range_start_value); - vars["orig_index"] = SimpleItoa(range_start); - printer->Print (vars, "{$range_start_value$, $orig_index$},"); - range_start += range_len; - n_ranges++; + vars["range_start_value"] = SimpleItoa(range_start_value); + vars["orig_index"] = SimpleItoa(range_start); + printer->Print (vars, "{$range_start_value$, $orig_index$},"); + range_start += range_len; + n_ranges++; } { - vars["range_start_value"] = SimpleItoa(0); - vars["orig_index"] = SimpleItoa(range_start); - printer->Print (vars, "{$range_start_value$, $orig_index$}\n};\n"); + vars["range_start_value"] = SimpleItoa(0); + vars["orig_index"] = SimpleItoa(range_start); + printer->Print (vars, "{$range_start_value$, $orig_index$}\n};\n"); } } vars["n_ranges"] = SimpleItoa(n_ranges); - qsort(value_index, descriptor_->value_count(), + if (!lite_runtime) { + qsort(value_index, descriptor_->value_count(), sizeof(ValueIndex), compare_value_indices_by_name); - printer->Print(vars, - "static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n" - "{\n"); - for (int j = 0; j < descriptor_->value_count(); j++) { - vars["index"] = SimpleItoa(value_index[j].final_index); - vars["name"] = value_index[j].name; - printer->Print (vars, " { \"$name$\", $index$ },\n"); + printer->Print(vars, + "static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n" + "{\n"); + for (int j = 0; j < descriptor_->value_count(); j++) { + vars["index"] = SimpleItoa(value_index[j].final_index); + vars["name"] = value_index[j].name; + printer->Print (vars, " { \"$name$\", $index$ },\n"); + } + printer->Print(vars, "};\n"); } - printer->Print(vars, "};\n"); - printer->Print(vars, - "const ProtobufCEnumDescriptor $lcclassname$__descriptor =\n" - "{\n" - " PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,\n" - " \"$fullname$\",\n" - " \"$shortname$\",\n" - " \"$cname$\",\n" - " \"$packagename$\",\n" - " $unique_value_count$,\n" - " $lcclassname$__enum_values_by_number,\n" - " $value_count$,\n" - " $lcclassname$__enum_values_by_name,\n" - " $n_ranges$,\n" - " $lcclassname$__value_ranges,\n" - " NULL,NULL,NULL,NULL /* reserved[1234] */\n" - "};\n"); + if (lite_runtime) { + printer->Print(vars, + "const ProtobufCEnumDescriptor $lcclassname$__descriptor =\n" + "{\n" + " PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,\n" + " NULL,NULL,NULL,NULL, /* LITE_RUNTIME */\n" + " $unique_value_count$,\n" + " $lcclassname$__enum_values_by_number,\n" + " 0, NULL, /* LITE_RUNTIME */\n" + " $n_ranges$,\n" + " $lcclassname$__value_ranges,\n" + " NULL,NULL,NULL,NULL /* reserved[1234] */\n" + "};\n"); + } else { + printer->Print(vars, + "const ProtobufCEnumDescriptor $lcclassname$__descriptor =\n" + "{\n" + " PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,\n" + " \"$fullname$\",\n" + " \"$shortname$\",\n" + " \"$cname$\",\n" + " \"$packagename$\",\n" + " $unique_value_count$,\n" + " $lcclassname$__enum_values_by_number,\n" + " $value_count$,\n" + " $lcclassname$__enum_values_by_name,\n" + " $n_ranges$,\n" + " $lcclassname$__value_ranges,\n" + " NULL,NULL,NULL,NULL /* reserved[1234] */\n" + "};\n"); + } delete[] value_index; delete[] name_index; diff --git a/protoc-c/c_field.cc b/protoc-c/c_field.cc index 96a7b52..2144135 100644 --- a/protoc-c/c_field.cc +++ b/protoc-c/c_field.cc @@ -139,9 +139,15 @@ void FieldGenerator::GenerateDescriptorInitializerGeneric(io::Printer* printer, if (oneof != NULL) variables["flags"] += " | PROTOBUF_C_FIELD_FLAG_ONEOF"; + printer->Print("{\n"); + if (descriptor_->file()->options().has_optimize_for() && + descriptor_->file()->options().optimize_for() == + FileOptions_OptimizeMode_LITE_RUNTIME) { + printer->Print(" NULL, /* LITE_RUNTIME */\n"); + } else { + printer->Print(variables, " \"$proto_name$\",\n"); + } printer->Print(variables, - "{\n" - " \"$proto_name$\",\n" " $value$,\n" " PROTOBUF_C_LABEL_$LABEL$,\n" " PROTOBUF_C_TYPE_$TYPE$,\n"); diff --git a/protoc-c/c_message.cc b/protoc-c/c_message.cc index 4a5ffab..f2b2a3f 100644 --- a/protoc-c/c_message.cc +++ b/protoc-c/c_message.cc @@ -387,6 +387,10 @@ GenerateMessageDescriptor(io::Printer* printer) { vars["n_fields"] = SimpleItoa(descriptor_->field_count()); vars["packagename"] = descriptor_->file()->package(); + bool lite_runtime = descriptor_->file()->options().has_optimize_for() && + descriptor_->file()->options().optimize_for() == + FileOptions_OptimizeMode_LITE_RUNTIME; + for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateMessageDescriptor(printer); } @@ -488,21 +492,23 @@ GenerateMessageDescriptor(io::Printer* printer) { printer->Outdent(); printer->Print(vars, "};\n"); - NameIndex *field_indices = new NameIndex [descriptor_->field_count()]; - for (int i = 0; i < descriptor_->field_count(); i++) { - field_indices[i].name = sorted_fields[i]->name().c_str(); - field_indices[i].index = i; + if (!lite_runtime) { + NameIndex *field_indices = new NameIndex [descriptor_->field_count()]; + for (int i = 0; i < descriptor_->field_count(); i++) { + field_indices[i].name = sorted_fields[i]->name().c_str(); + field_indices[i].index = i; + } + qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex), + compare_name_indices_by_name); + 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"); + delete[] field_indices; } - qsort (field_indices, descriptor_->field_count(), sizeof (NameIndex), - compare_name_indices_by_name); - 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"); - delete[] field_indices; // create range initializers int *values = new int[descriptor_->field_count()]; @@ -526,24 +532,36 @@ GenerateMessageDescriptor(io::Printer* printer) { "#define $lcclassname$__field_indices_by_name NULL\n" "#define $lcclassname$__number_ranges NULL\n"); } - + printer->Print(vars, - "const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n" - "{\n" - " PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n" - " \"$fullname$\",\n" - " \"$shortname$\",\n" - " \"$classname$\",\n" - " \"$packagename$\",\n" - " sizeof($classname$),\n" - " $n_fields$,\n" - " $lcclassname$__field_descriptors,\n" - " $lcclassname$__field_indices_by_name,\n" - " $n_ranges$," - " $lcclassname$__number_ranges,\n" - " (ProtobufCMessageInit) $lcclassname$__init,\n" - " NULL,NULL,NULL /* reserved[123] */\n" - "};\n"); + "const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n" + "{\n" + " PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n"); + if (lite_runtime) { + printer->Print(" NULL,NULL,NULL,NULL, /* LITE_RUNTIME */\n"); + } else { + printer->Print(vars, + " \"$fullname$\",\n" + " \"$shortname$\",\n" + " \"$classname$\",\n" + " \"$packagename$\",\n"); + } + printer->Print(vars, + " sizeof($classname$),\n" + " $n_fields$,\n" + " $lcclassname$__field_descriptors,\n"); + if (lite_runtime) { + printer->Print(" NULL, /* LITE_RUNTIME */\n"); + } else { + printer->Print(vars, + " $lcclassname$__field_indices_by_name,\n"); + } + printer->Print(vars, + " $n_ranges$," + " $lcclassname$__number_ranges,\n" + " (ProtobufCMessageInit) $lcclassname$__init,\n" + " NULL,NULL,NULL /* reserved[123] */\n" + "};\n"); } } // namespace c diff --git a/protoc-c/c_service.cc b/protoc-c/c_service.cc index 183d750..af54156 100644 --- a/protoc-c/c_service.cc +++ b/protoc-c/c_service.cc @@ -198,6 +198,10 @@ void ServiceGenerator::GenerateServiceDescriptor(io::Printer* printer) int n_methods = descriptor_->method_count(); MethodIndexAndName *mi_array = new MethodIndexAndName[n_methods]; + bool lite_runtime = descriptor_->file()->options().has_optimize_for() && + descriptor_->file()->options().optimize_for() == + FileOptions_OptimizeMode_LITE_RUNTIME; + vars_["n_methods"] = SimpleItoa(n_methods); printer->Print(vars_, "static const ProtobufCMethodDescriptor $lcfullname$__method_descriptors[$n_methods$] =\n" "{\n"); @@ -206,37 +210,54 @@ void ServiceGenerator::GenerateServiceDescriptor(io::Printer* printer) vars_["method"] = method->name(); vars_["input_descriptor"] = "&" + FullNameToLower(method->input_type()->full_name()) + "__descriptor"; vars_["output_descriptor"] = "&" + FullNameToLower(method->output_type()->full_name()) + "__descriptor"; - printer->Print(vars_, - " { \"$method$\", $input_descriptor$, $output_descriptor$ },\n"); + if (lite_runtime) { + printer->Print(vars_, + " { NULL, $input_descriptor$, $output_descriptor$ }, /* LITE_RUNTIME */\n"); + } else { + printer->Print(vars_, + " { \"$method$\", $input_descriptor$, $output_descriptor$ },\n"); + } mi_array[i].i = i; mi_array[i].name = method->name().c_str(); } printer->Print(vars_, "};\n"); - qsort ((void*)mi_array, n_methods, sizeof (MethodIndexAndName), - compare_method_index_and_name_by_name); - printer->Print(vars_, "const unsigned $lcfullname$__method_indices_by_name[] = {\n"); - for (int i = 0; i < n_methods; i++) { - vars_["i"] = SimpleItoa(mi_array[i].i); - vars_["name"] = mi_array[i].name; - vars_["comma"] = (i + 1 < n_methods) ? "," : " "; - printer->Print(vars_, " $i$$comma$ /* $name$ */\n"); + if (!lite_runtime) { + qsort ((void*)mi_array, n_methods, sizeof (MethodIndexAndName), + compare_method_index_and_name_by_name); + printer->Print(vars_, "const unsigned $lcfullname$__method_indices_by_name[] = {\n"); + for (int i = 0; i < n_methods; i++) { + vars_["i"] = SimpleItoa(mi_array[i].i); + vars_["name"] = mi_array[i].name; + vars_["comma"] = (i + 1 < n_methods) ? "," : " "; + printer->Print(vars_, " $i$$comma$ /* $name$ */\n"); + } + printer->Print(vars_, "};\n"); + vars_["name"] = descriptor_->name(); } - printer->Print(vars_, "};\n"); - vars_["name"] = descriptor_->name(); - - printer->Print(vars_, "const ProtobufCServiceDescriptor $lcfullname$__descriptor =\n" - "{\n" - " PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC,\n" - " \"$fullname$\",\n" - " \"$name$\",\n" - " \"$cname$\",\n" - " \"$package$\",\n" - " $n_methods$,\n" - " $lcfullname$__method_descriptors,\n" - " $lcfullname$__method_indices_by_name\n" - "};\n"); + if (lite_runtime) { + printer->Print(vars_, "const ProtobufCServiceDescriptor $lcfullname$__descriptor =\n" + "{\n" + " PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC,\n" + " NULL,NULL,NULL,NULL, /* LITE_RUNTIME */\n" + " $n_methods$,\n" + " $lcfullname$__method_descriptors,\n" + " NULL /* LITE_RUNTIME */\n" + "};\n"); + } else { + printer->Print(vars_, "const ProtobufCServiceDescriptor $lcfullname$__descriptor =\n" + "{\n" + " PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC,\n" + " \"$fullname$\",\n" + " \"$name$\",\n" + " \"$cname$\",\n" + " \"$package$\",\n" + " $n_methods$,\n" + " $lcfullname$__method_descriptors,\n" + " $lcfullname$__method_indices_by_name\n" + "};\n"); + } delete[] mi_array; }