Skip to content

Commit 8c6dcd0

Browse files
[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
1 parent 9ca411a commit 8c6dcd0

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

src/google/protobuf/compiler/objectivec/message.cc

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "google/protobuf/compiler/objectivec/names.h"
4747
#include "google/protobuf/compiler/objectivec/oneof.h"
4848
#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
49+
#include "google/protobuf/descriptor.h"
4950
#include "google/protobuf/descriptor.pb.h"
5051
#include "google/protobuf/io/printer.h"
5152

@@ -153,6 +154,39 @@ struct ExtensionRangeOrdering {
153154
}
154155
};
155156

157+
// This is a reduced case of Descriptor::ExtensionRange with just start and end.
158+
struct SimpleExtensionRange {
159+
SimpleExtensionRange(int start, int end) : start(start), end(end){};
160+
int start; // inclusive
161+
int end; // exclusive
162+
163+
// Descriptors expose extension ranges in the order they were defined in the
164+
// file, but this reorders and merges the ranges that are contiguous (i.e. -
165+
// [(21,30),(10,20)] -> [(10,30)])
166+
static std::vector<SimpleExtensionRange> Normalize(
167+
const Descriptor* descriptor) {
168+
std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
169+
sorted_extensions.reserve(descriptor->extension_range_count());
170+
for (int i = 0; i < descriptor->extension_range_count(); ++i) {
171+
sorted_extensions.push_back(descriptor->extension_range(i));
172+
}
173+
174+
std::sort(sorted_extensions.begin(), sorted_extensions.end(),
175+
ExtensionRangeOrdering());
176+
177+
std::vector<SimpleExtensionRange> result;
178+
result.reserve(sorted_extensions.size());
179+
for (const auto ext : sorted_extensions) {
180+
if (!result.empty() && result.back().end == ext->start) {
181+
result.back().end = ext->end;
182+
} else {
183+
result.emplace_back(ext->start, ext->end);
184+
}
185+
}
186+
return result;
187+
}
188+
};
189+
156190
// Sort the fields of the given Descriptor by number into a new[]'d array
157191
// and return it.
158192
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
@@ -387,14 +421,8 @@ void MessageGenerator::GenerateSource(io::Printer* printer) const {
387421
std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
388422
SortFieldsByStorageSize(descriptor_));
389423

390-
std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
391-
sorted_extensions.reserve(descriptor_->extension_range_count());
392-
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
393-
sorted_extensions.push_back(descriptor_->extension_range(i));
394-
}
395-
396-
std::sort(sorted_extensions.begin(), sorted_extensions.end(),
397-
ExtensionRangeOrdering());
424+
std::vector<SimpleExtensionRange> sorted_extensions(
425+
SimpleExtensionRange::Normalize(descriptor_));
398426

399427
printer->Print(
400428
// clang-format off
@@ -528,10 +556,10 @@ void MessageGenerator::GenerateSource(io::Printer* printer) const {
528556
}
529557
if (!sorted_extensions.empty()) {
530558
printer->Print(" static const GPBExtensionRange ranges[] = {\n");
531-
for (int i = 0; i < sorted_extensions.size(); i++) {
559+
for (const auto& extension_range : sorted_extensions) {
532560
printer->Print(" { .start = $start$, .end = $end$ },\n", "start",
533-
absl::StrCat(sorted_extensions[i]->start), "end",
534-
absl::StrCat(sorted_extensions[i]->end));
561+
absl::StrCat(extension_range.start), "end",
562+
absl::StrCat(extension_range.end));
535563
}
536564
// clang-format off
537565
printer->Print(

0 commit comments

Comments
 (0)