Home | History | Annotate | Download | only in objectivec
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 #include <algorithm>
     32 #include <iostream>
     33 #include <sstream>
     34 
     35 #include <google/protobuf/stubs/hash.h>
     36 #include <google/protobuf/compiler/objectivec/objectivec_message.h>
     37 #include <google/protobuf/compiler/objectivec/objectivec_enum.h>
     38 #include <google/protobuf/compiler/objectivec/objectivec_extension.h>
     39 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
     40 #include <google/protobuf/stubs/stl_util.h>
     41 #include <google/protobuf/stubs/strutil.h>
     42 #include <google/protobuf/io/printer.h>
     43 #include <google/protobuf/io/coded_stream.h>
     44 #include <google/protobuf/io/zero_copy_stream_impl.h>
     45 #include <google/protobuf/wire_format.h>
     46 #include <google/protobuf/wire_format_lite_inl.h>
     47 #include <google/protobuf/descriptor.pb.h>
     48 
     49 namespace google {
     50 namespace protobuf {
     51 namespace compiler {
     52 namespace objectivec {
     53 
     54 using internal::WireFormat;
     55 using internal::WireFormatLite;
     56 
     57 namespace {
     58 struct FieldOrderingByNumber {
     59   inline bool operator()(const FieldDescriptor* a,
     60                          const FieldDescriptor* b) const {
     61     return a->number() < b->number();
     62   }
     63 };
     64 
     65 int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
     66   // The first item in the object structure is our uint32[] for has bits.
     67   // We then want to order things to make the instances as small as
     68   // possible. So we follow the has bits with:
     69   //   1. Anything always 4 bytes - float, *32, enums
     70   //   2. Anything that is always a pointer (they will be 8 bytes on 64 bit
     71   //      builds and 4 bytes on 32bit builds.
     72   //   3. Anything always 8 bytes - double, *64
     73   //
     74   // NOTE: Bools aren't listed, they were stored in the has bits.
     75   //
     76   // Why? Using 64bit builds as an example, this means worse case, we have
     77   // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
     78   // are wasted before the 4 byte values. Then if we have an odd number of
     79   // those 4 byte values, the 8 byte values will be pushed down by 32bits to
     80   // keep them aligned. But the structure will end 8 byte aligned, so no
     81   // waste on the end. If you did the reverse order, you could waste 4 bytes
     82   // before the first 8 byte value (after the has array), then a single
     83   // bool on the end would need 7 bytes of padding to make the overall
     84   // structure 8 byte aligned; so 11 bytes, wasted total.
     85 
     86   // Anything repeated is a GPB*Array/NSArray, so pointer.
     87   if (descriptor->is_repeated()) {
     88     return 3;
     89   }
     90 
     91   switch (descriptor->type()) {
     92     // All always 8 bytes.
     93     case FieldDescriptor::TYPE_DOUBLE:
     94     case FieldDescriptor::TYPE_INT64:
     95     case FieldDescriptor::TYPE_SINT64:
     96     case FieldDescriptor::TYPE_UINT64:
     97     case FieldDescriptor::TYPE_SFIXED64:
     98     case FieldDescriptor::TYPE_FIXED64:
     99       return 4;
    100 
    101     // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
    102     // depending on the build architecture.
    103     case FieldDescriptor::TYPE_GROUP:
    104     case FieldDescriptor::TYPE_MESSAGE:
    105     case FieldDescriptor::TYPE_STRING:
    106     case FieldDescriptor::TYPE_BYTES:
    107       return 3;
    108 
    109     // All always 4 bytes (enums are int32s).
    110     case FieldDescriptor::TYPE_FLOAT:
    111     case FieldDescriptor::TYPE_INT32:
    112     case FieldDescriptor::TYPE_SINT32:
    113     case FieldDescriptor::TYPE_UINT32:
    114     case FieldDescriptor::TYPE_SFIXED32:
    115     case FieldDescriptor::TYPE_FIXED32:
    116     case FieldDescriptor::TYPE_ENUM:
    117       return 2;
    118 
    119     // 0 bytes. Stored in the has bits.
    120     case FieldDescriptor::TYPE_BOOL:
    121       return 99;  // End of the list (doesn't really matter).
    122   }
    123 
    124   // Some compilers report reaching end of function even though all cases of
    125   // the enum are handed in the switch.
    126   GOOGLE_LOG(FATAL) << "Can't get here.";
    127   return 0;
    128 }
    129 
    130 struct FieldOrderingByStorageSize {
    131   inline bool operator()(const FieldDescriptor* a,
    132                          const FieldDescriptor* b) const {
    133     // Order by grouping.
    134     const int order_group_a = OrderGroupForFieldDescriptor(a);
    135     const int order_group_b = OrderGroupForFieldDescriptor(b);
    136     if (order_group_a != order_group_b) {
    137       return order_group_a < order_group_b;
    138     }
    139     // Within the group, order by field number (provides stable ordering).
    140     return a->number() < b->number();
    141   }
    142 };
    143 
    144 struct ExtensionRangeOrdering {
    145   bool operator()(const Descriptor::ExtensionRange* a,
    146                   const Descriptor::ExtensionRange* b) const {
    147     return a->start < b->start;
    148   }
    149 };
    150 
    151 // Sort the fields of the given Descriptor by number into a new[]'d array
    152 // and return it.
    153 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
    154   const FieldDescriptor** fields =
    155       new const FieldDescriptor* [descriptor->field_count()];
    156   for (int i = 0; i < descriptor->field_count(); i++) {
    157     fields[i] = descriptor->field(i);
    158   }
    159   sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
    160   return fields;
    161 }
    162 
    163 // Sort the fields of the given Descriptor by storage size into a new[]'d
    164 // array and return it.
    165 const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
    166   const FieldDescriptor** fields =
    167       new const FieldDescriptor* [descriptor->field_count()];
    168   for (int i = 0; i < descriptor->field_count(); i++) {
    169     fields[i] = descriptor->field(i);
    170   }
    171   sort(fields, fields + descriptor->field_count(),
    172        FieldOrderingByStorageSize());
    173   return fields;
    174 }
    175 }  // namespace
    176 
    177 MessageGenerator::MessageGenerator(const string& root_classname,
    178                                    const Descriptor* descriptor,
    179                                    const Options& options)
    180     : root_classname_(root_classname),
    181       descriptor_(descriptor),
    182       field_generators_(descriptor, options),
    183       class_name_(ClassName(descriptor_)) {
    184   for (int i = 0; i < descriptor_->extension_count(); i++) {
    185     extension_generators_.push_back(
    186         new ExtensionGenerator(class_name_, descriptor_->extension(i)));
    187   }
    188 
    189   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
    190     OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
    191     oneof_generators_.push_back(generator);
    192   }
    193 
    194   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
    195     EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
    196     enum_generators_.push_back(generator);
    197   }
    198 
    199   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    200     MessageGenerator* generator =
    201         new MessageGenerator(root_classname_,
    202                              descriptor_->nested_type(i),
    203                              options);
    204     nested_message_generators_.push_back(generator);
    205   }
    206 }
    207 
    208 MessageGenerator::~MessageGenerator() {
    209   STLDeleteContainerPointers(extension_generators_.begin(),
    210                              extension_generators_.end());
    211   STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
    212   STLDeleteContainerPointers(nested_message_generators_.begin(),
    213                              nested_message_generators_.end());
    214   STLDeleteContainerPointers(oneof_generators_.begin(),
    215                              oneof_generators_.end());
    216 }
    217 
    218 void MessageGenerator::GenerateStaticVariablesInitialization(
    219     io::Printer* printer) {
    220   for (vector<ExtensionGenerator*>::iterator iter =
    221            extension_generators_.begin();
    222        iter != extension_generators_.end(); ++iter) {
    223     (*iter)->GenerateStaticVariablesInitialization(printer);
    224   }
    225 
    226   for (vector<MessageGenerator*>::iterator iter =
    227            nested_message_generators_.begin();
    228        iter != nested_message_generators_.end(); ++iter) {
    229     (*iter)->GenerateStaticVariablesInitialization(printer);
    230   }
    231 }
    232 
    233 void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
    234   if (!IsMapEntryMessage(descriptor_)) {
    235     for (int i = 0; i < descriptor_->field_count(); i++) {
    236       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
    237       field_generators_.get(fieldDescriptor)
    238           .DetermineForwardDeclarations(fwd_decls);
    239     }
    240   }
    241 
    242   for (vector<MessageGenerator*>::iterator iter =
    243            nested_message_generators_.begin();
    244        iter != nested_message_generators_.end(); ++iter) {
    245     (*iter)->DetermineForwardDeclarations(fwd_decls);
    246   }
    247 }
    248 
    249 void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
    250   for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
    251        iter != enum_generators_.end(); ++iter) {
    252     (*iter)->GenerateHeader(printer);
    253   }
    254 
    255   for (vector<MessageGenerator*>::iterator iter =
    256            nested_message_generators_.begin();
    257        iter != nested_message_generators_.end(); ++iter) {
    258     (*iter)->GenerateEnumHeader(printer);
    259   }
    260 }
    261 
    262 void MessageGenerator::GenerateExtensionRegistrationSource(
    263     io::Printer* printer) {
    264   for (vector<ExtensionGenerator*>::iterator iter =
    265            extension_generators_.begin();
    266        iter != extension_generators_.end(); ++iter) {
    267     (*iter)->GenerateRegistrationSource(printer);
    268   }
    269 
    270   for (vector<MessageGenerator*>::iterator iter =
    271            nested_message_generators_.begin();
    272        iter != nested_message_generators_.end(); ++iter) {
    273     (*iter)->GenerateExtensionRegistrationSource(printer);
    274   }
    275 }
    276 
    277 void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
    278   // This a a map entry message, just recurse and do nothing directly.
    279   if (IsMapEntryMessage(descriptor_)) {
    280     for (vector<MessageGenerator*>::iterator iter =
    281              nested_message_generators_.begin();
    282          iter != nested_message_generators_.end(); ++iter) {
    283       (*iter)->GenerateMessageHeader(printer);
    284     }
    285     return;
    286   }
    287 
    288   printer->Print(
    289       "#pragma mark - $classname$\n"
    290       "\n",
    291       "classname", class_name_);
    292 
    293   if (descriptor_->field_count()) {
    294     scoped_array<const FieldDescriptor*> sorted_fields(
    295         SortFieldsByNumber(descriptor_));
    296 
    297     printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
    298                    "classname", class_name_);
    299     printer->Indent();
    300 
    301     for (int i = 0; i < descriptor_->field_count(); i++) {
    302       field_generators_.get(sorted_fields[i])
    303           .GenerateFieldNumberConstant(printer);
    304     }
    305 
    306     printer->Outdent();
    307     printer->Print("};\n\n");
    308   }
    309 
    310   for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
    311        iter != oneof_generators_.end(); ++iter) {
    312     (*iter)->GenerateCaseEnum(printer);
    313   }
    314 
    315   string message_comments;
    316   SourceLocation location;
    317   if (descriptor_->GetSourceLocation(&location)) {
    318     message_comments = BuildCommentsString(location);
    319   } else {
    320     message_comments = "";
    321   }
    322 
    323   printer->Print(
    324       "$comments$$deprecated_attribute$@interface $classname$ : GPBMessage\n\n",
    325       "classname", class_name_,
    326       "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, false, true),
    327       "comments", message_comments);
    328 
    329   vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
    330   for (int i = 0; i < descriptor_->field_count(); i++) {
    331     const FieldDescriptor* field = descriptor_->field(i);
    332     if (field->containing_oneof() != NULL) {
    333       const int oneof_index = field->containing_oneof()->index();
    334       if (!seen_oneofs[oneof_index]) {
    335         seen_oneofs[oneof_index] = 1;
    336         oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
    337             printer);
    338       }
    339     }
    340     field_generators_.get(field).GeneratePropertyDeclaration(printer);
    341   }
    342 
    343   printer->Print("@end\n\n");
    344 
    345   for (int i = 0; i < descriptor_->field_count(); i++) {
    346     field_generators_.get(descriptor_->field(i))
    347         .GenerateCFunctionDeclarations(printer);
    348   }
    349 
    350   if (!oneof_generators_.empty()) {
    351     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
    352          iter != oneof_generators_.end(); ++iter) {
    353       (*iter)->GenerateClearFunctionDeclaration(printer);
    354     }
    355     printer->Print("\n");
    356   }
    357 
    358   if (descriptor_->extension_count() > 0) {
    359     printer->Print("@interface $classname$ (DynamicMethods)\n\n",
    360                    "classname", class_name_);
    361     for (vector<ExtensionGenerator*>::iterator iter =
    362              extension_generators_.begin();
    363          iter != extension_generators_.end(); ++iter) {
    364       (*iter)->GenerateMembersHeader(printer);
    365     }
    366     printer->Print("@end\n\n");
    367   }
    368 
    369   for (vector<MessageGenerator*>::iterator iter =
    370            nested_message_generators_.begin();
    371        iter != nested_message_generators_.end(); ++iter) {
    372     (*iter)->GenerateMessageHeader(printer);
    373   }
    374 }
    375 
    376 void MessageGenerator::GenerateSource(io::Printer* printer) {
    377   if (!IsMapEntryMessage(descriptor_)) {
    378     printer->Print(
    379         "#pragma mark - $classname$\n"
    380         "\n",
    381         "classname", class_name_);
    382 
    383     printer->Print("@implementation $classname$\n\n",
    384                    "classname", class_name_);
    385 
    386     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
    387          iter != oneof_generators_.end(); ++iter) {
    388       (*iter)->GeneratePropertyImplementation(printer);
    389     }
    390 
    391     for (int i = 0; i < descriptor_->field_count(); i++) {
    392       field_generators_.get(descriptor_->field(i))
    393           .GeneratePropertyImplementation(printer);
    394     }
    395 
    396     scoped_array<const FieldDescriptor*> sorted_fields(
    397         SortFieldsByNumber(descriptor_));
    398     scoped_array<const FieldDescriptor*> size_order_fields(
    399         SortFieldsByStorageSize(descriptor_));
    400 
    401     vector<const Descriptor::ExtensionRange*> sorted_extensions;
    402     for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
    403       sorted_extensions.push_back(descriptor_->extension_range(i));
    404     }
    405 
    406     sort(sorted_extensions.begin(), sorted_extensions.end(),
    407          ExtensionRangeOrdering());
    408 
    409     // Assign has bits:
    410     // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
    411     //    who needs has bits and assigning them.
    412     // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
    413     //    index that groups all the elements in the oneof.
    414     size_t num_has_bits = field_generators_.CalculateHasBits();
    415     size_t sizeof_has_storage = (num_has_bits + 31) / 32;
    416     if (sizeof_has_storage == 0) {
    417       // In the case where no field needs has bits, don't let the _has_storage_
    418       // end up as zero length (zero length arrays are sort of a grey area
    419       // since it has to be at the start of the struct). This also ensures a
    420       // field with only oneofs keeps the required negative indices they need.
    421       sizeof_has_storage = 1;
    422     }
    423     // Tell all the fields the oneof base.
    424     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
    425          iter != oneof_generators_.end(); ++iter) {
    426       (*iter)->SetOneofIndexBase(sizeof_has_storage);
    427     }
    428     field_generators_.SetOneofIndexBase(sizeof_has_storage);
    429     // sizeof_has_storage needs enough bits for the single fields that aren't in
    430     // any oneof, and then one int32 for each oneof (to store the field number).
    431     sizeof_has_storage += descriptor_->oneof_decl_count();
    432 
    433     printer->Print(
    434         "\n"
    435         "typedef struct $classname$__storage_ {\n"
    436         "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
    437         "classname", class_name_,
    438         "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
    439     printer->Indent();
    440 
    441     for (int i = 0; i < descriptor_->field_count(); i++) {
    442       field_generators_.get(size_order_fields[i])
    443           .GenerateFieldStorageDeclaration(printer);
    444     }
    445     printer->Outdent();
    446 
    447     printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
    448 
    449 
    450     printer->Print(
    451         "// This method is threadsafe because it is initially called\n"
    452         "// in +initialize for each subclass.\n"
    453         "+ (GPBDescriptor *)descriptor {\n"
    454         "  static GPBDescriptor *descriptor = nil;\n"
    455         "  if (!descriptor) {\n");
    456 
    457     TextFormatDecodeData text_format_decode_data;
    458     bool has_fields = descriptor_->field_count() > 0;
    459     bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
    460     string field_description_type;
    461     if (need_defaults) {
    462       field_description_type = "GPBMessageFieldDescriptionWithDefault";
    463     } else {
    464       field_description_type = "GPBMessageFieldDescription";
    465     }
    466     if (has_fields) {
    467       printer->Print(
    468           "    static $field_description_type$ fields[] = {\n",
    469           "field_description_type", field_description_type);
    470       printer->Indent();
    471       printer->Indent();
    472       printer->Indent();
    473       for (int i = 0; i < descriptor_->field_count(); ++i) {
    474         const FieldGenerator& field_generator =
    475             field_generators_.get(sorted_fields[i]);
    476         field_generator.GenerateFieldDescription(printer, need_defaults);
    477         if (field_generator.needs_textformat_name_support()) {
    478           text_format_decode_data.AddString(sorted_fields[i]->number(),
    479                                             field_generator.generated_objc_name(),
    480                                             field_generator.raw_field_name());
    481         }
    482       }
    483       printer->Outdent();
    484       printer->Outdent();
    485       printer->Outdent();
    486       printer->Print(
    487           "    };\n");
    488     }
    489 
    490     map<string, string> vars;
    491     vars["classname"] = class_name_;
    492     vars["rootclassname"] = root_classname_;
    493     vars["fields"] = has_fields ? "fields" : "NULL";
    494     if (has_fields) {
    495       vars["fields_count"] =
    496           "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
    497     } else {
    498       vars["fields_count"] = "0";
    499     }
    500 
    501     std::vector<string> init_flags;
    502     if (need_defaults) {
    503       init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
    504     }
    505     if (descriptor_->options().message_set_wire_format()) {
    506       init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
    507     }
    508     vars["init_flags"] = BuildFlagsString(init_flags);
    509 
    510     printer->Print(
    511         vars,
    512         "    GPBDescriptor *localDescriptor =\n"
    513         "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
    514         "                                     rootClass:[$rootclassname$ class]\n"
    515         "                                          file:$rootclassname$_FileDescriptor()\n"
    516         "                                        fields:$fields$\n"
    517         "                                    fieldCount:$fields_count$\n"
    518         "                                   storageSize:sizeof($classname$__storage_)\n"
    519         "                                         flags:$init_flags$];\n");
    520     if (oneof_generators_.size() != 0) {
    521       printer->Print(
    522           "    static const char *oneofs[] = {\n");
    523       for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
    524            iter != oneof_generators_.end(); ++iter) {
    525         printer->Print(
    526             "      \"$name$\",\n",
    527             "name", (*iter)->DescriptorName());
    528       }
    529       printer->Print(
    530           "    };\n"
    531           "    [localDescriptor setupOneofs:oneofs\n"
    532           "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
    533           "                   firstHasIndex:$first_has_index$];\n",
    534           "first_has_index", oneof_generators_[0]->HasIndexAsString());
    535     }
    536     if (text_format_decode_data.num_entries() != 0) {
    537       const string text_format_data_str(text_format_decode_data.Data());
    538       printer->Print(
    539           "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
    540           "    static const char *extraTextFormatInfo =");
    541       static const int kBytesPerLine = 40;  // allow for escaping
    542       for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
    543         printer->Print(
    544             "\n        \"$data$\"",
    545             "data", EscapeTrigraphs(
    546                 CEscape(text_format_data_str.substr(i, kBytesPerLine))));
    547       }
    548       printer->Print(
    549           ";\n"
    550           "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
    551           "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
    552     }
    553     if (sorted_extensions.size() != 0) {
    554       printer->Print(
    555           "    static const GPBExtensionRange ranges[] = {\n");
    556       for (int i = 0; i < sorted_extensions.size(); i++) {
    557         printer->Print("      { .start = $start$, .end = $end$ },\n",
    558                        "start", SimpleItoa(sorted_extensions[i]->start),
    559                        "end", SimpleItoa(sorted_extensions[i]->end));
    560       }
    561       printer->Print(
    562           "    };\n"
    563           "    [localDescriptor setupExtensionRanges:ranges\n"
    564           "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
    565     }
    566     printer->Print(
    567         "    NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
    568         "    descriptor = localDescriptor;\n"
    569         "  }\n"
    570         "  return descriptor;\n"
    571         "}\n\n"
    572         "@end\n\n");
    573 
    574     for (int i = 0; i < descriptor_->field_count(); i++) {
    575       field_generators_.get(descriptor_->field(i))
    576           .GenerateCFunctionImplementations(printer);
    577     }
    578 
    579     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
    580          iter != oneof_generators_.end(); ++iter) {
    581       (*iter)->GenerateClearFunctionImplementation(printer);
    582     }
    583   }
    584 
    585   for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
    586        iter != enum_generators_.end(); ++iter) {
    587     (*iter)->GenerateSource(printer);
    588   }
    589 
    590   for (vector<MessageGenerator*>::iterator iter =
    591            nested_message_generators_.begin();
    592        iter != nested_message_generators_.end(); ++iter) {
    593     (*iter)->GenerateSource(printer);
    594   }
    595 }
    596 
    597 }  // namespace objectivec
    598 }  // namespace compiler
    599 }  // namespace protobuf
    600 }  // namespace google
    601