[ObjC] Merge extension ranges that are continues.

Can result in a small reduction in binary size as well as slight performance
improvement during serialization since it is less subcalls for writing out any
extensions in the ranges.

PiperOrigin-RevId: 504272482
pull/11639/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 9ca411a46b
commit 8c6dcd05cd
  1. 50
      src/google/protobuf/compiler/objectivec/message.cc

@ -46,6 +46,7 @@
#include "google/protobuf/compiler/objectivec/names.h"
#include "google/protobuf/compiler/objectivec/oneof.h"
#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/printer.h"
@ -153,6 +154,39 @@ struct ExtensionRangeOrdering {
}
};
// This is a reduced case of Descriptor::ExtensionRange with just start and end.
struct SimpleExtensionRange {
SimpleExtensionRange(int start, int end) : start(start), end(end){};
int start; // inclusive
int end; // exclusive
// Descriptors expose extension ranges in the order they were defined in the
// file, but this reorders and merges the ranges that are contiguous (i.e. -
// [(21,30),(10,20)] -> [(10,30)])
static std::vector<SimpleExtensionRange> Normalize(
const Descriptor* descriptor) {
std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
sorted_extensions.reserve(descriptor->extension_range_count());
for (int i = 0; i < descriptor->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor->extension_range(i));
}
std::sort(sorted_extensions.begin(), sorted_extensions.end(),
ExtensionRangeOrdering());
std::vector<SimpleExtensionRange> result;
result.reserve(sorted_extensions.size());
for (const auto ext : sorted_extensions) {
if (!result.empty() && result.back().end == ext->start) {
result.back().end = ext->end;
} else {
result.emplace_back(ext->start, ext->end);
}
}
return result;
}
};
// Sort the fields of the given Descriptor by number into a new[]'d array
// and return it.
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
@ -387,14 +421,8 @@ void MessageGenerator::GenerateSource(io::Printer* printer) const {
std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
SortFieldsByStorageSize(descriptor_));
std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
sorted_extensions.reserve(descriptor_->extension_range_count());
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor_->extension_range(i));
}
std::sort(sorted_extensions.begin(), sorted_extensions.end(),
ExtensionRangeOrdering());
std::vector<SimpleExtensionRange> sorted_extensions(
SimpleExtensionRange::Normalize(descriptor_));
printer->Print(
// clang-format off
@ -528,10 +556,10 @@ void MessageGenerator::GenerateSource(io::Printer* printer) const {
}
if (!sorted_extensions.empty()) {
printer->Print(" static const GPBExtensionRange ranges[] = {\n");
for (int i = 0; i < sorted_extensions.size(); i++) {
for (const auto& extension_range : sorted_extensions) {
printer->Print(" { .start = $start$, .end = $end$ },\n", "start",
absl::StrCat(sorted_extensions[i]->start), "end",
absl::StrCat(sorted_extensions[i]->end));
absl::StrCat(extension_range.start), "end",
absl::StrCat(extension_range.end));
}
// clang-format off
printer->Print(

Loading…
Cancel
Save