@ -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 (