Commit 603e4318 authored by Ilya Lipnitskiy's avatar Ilya Lipnitskiy

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.
parent 8601458e
......@@ -150,9 +150,15 @@ void EnumGenerator::GenerateValueInitializer(io::Printer *printer, int index)
{
const EnumValueDescriptor *vd = descriptor_->value(index);
map<string, string> 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());
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");
}
......@@ -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()];
......@@ -266,6 +276,7 @@ void EnumGenerator::GenerateEnumDescriptor(io::Printer* printer) {
}
vars["n_ranges"] = SimpleItoa(n_ranges);
if (!lite_runtime) {
qsort(value_index, descriptor_->value_count(),
sizeof(ValueIndex), compare_value_indices_by_name);
printer->Print(vars,
......@@ -277,7 +288,22 @@ void EnumGenerator::GenerateEnumDescriptor(io::Printer* printer) {
printer->Print (vars, " { \"$name$\", $index$ },\n");
}
printer->Print(vars, "};\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"
......@@ -294,6 +320,7 @@ void EnumGenerator::GenerateEnumDescriptor(io::Printer* printer) {
" $lcclassname$__value_ranges,\n"
" NULL,NULL,NULL,NULL /* reserved[1234] */\n"
"};\n");
}
delete[] value_index;
delete[] name_index;
......
......@@ -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");
......
......@@ -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,6 +492,7 @@ GenerateMessageDescriptor(io::Printer* printer) {
printer->Outdent();
printer->Print(vars, "};\n");
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();
......@@ -503,6 +508,7 @@ GenerateMessageDescriptor(io::Printer* printer) {
}
printer->Print("};\n");
delete[] field_indices;
}
// create range initializers
int *values = new int[descriptor_->field_count()];
......@@ -530,15 +536,27 @@ GenerateMessageDescriptor(io::Printer* printer) {
printer->Print(vars,
"const ProtobufCMessageDescriptor $lcclassname$__descriptor =\n"
"{\n"
" PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\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"
" \"$packagename$\",\n");
}
printer->Print(vars,
" sizeof($classname$),\n"
" $n_fields$,\n"
" $lcclassname$__field_descriptors,\n"
" $lcclassname$__field_indices_by_name,\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"
......
......@@ -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,13 +210,19 @@ 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";
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");
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");
......@@ -223,9 +233,19 @@ void ServiceGenerator::GenerateServiceDescriptor(io::Printer* printer)
printer->Print(vars_, " $i$$comma$ /* $name$ */\n");
}
printer->Print(vars_, "};\n");
vars_["name"] = descriptor_->name();
}
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"
......@@ -237,6 +257,7 @@ void ServiceGenerator::GenerateServiceDescriptor(io::Printer* printer)
" $lcfullname$__method_descriptors,\n"
" $lcfullname$__method_indices_by_name\n"
"};\n");
}
delete[] mi_array;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment