mirror of
https://github.com/protobuf-c/protobuf-c.git
synced 2025-01-14 01:07:57 +08:00
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.
This commit is contained in:
parent
8601458e5c
commit
603e431864
@ -150,11 +150,17 @@ 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());
|
||||
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;
|
||||
|
@ -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,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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user