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 {
operator ()google::protobuf::compiler::objectivec::__anon73dbe1210111::FieldOrderingByNumber59   inline bool operator()(const FieldDescriptor* a,
60                          const FieldDescriptor* b) const {
61     return a->number() < b->number();
62   }
63 };
64 
OrderGroupForFieldDescriptor(const FieldDescriptor * descriptor)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 {
operator ()google::protobuf::compiler::objectivec::__anon73dbe1210111::FieldOrderingByStorageSize131   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 {
operator ()google::protobuf::compiler::objectivec::__anon73dbe1210111::ExtensionRangeOrdering145   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.
SortFieldsByNumber(const Descriptor * descriptor)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.
SortFieldsByStorageSize(const Descriptor * descriptor)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 
MessageGenerator(const string & root_classname,const Descriptor * descriptor,const Options & options)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 
~MessageGenerator()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 
GenerateStaticVariablesInitialization(io::Printer * printer)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 
DetermineForwardDeclarations(set<string> * fwd_decls)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 
IncludesOneOfDefinition() const249 bool MessageGenerator::IncludesOneOfDefinition() const {
250   if (!oneof_generators_.empty()) {
251     return true;
252   }
253 
254   for (vector<MessageGenerator*>::const_iterator iter =
255            nested_message_generators_.begin();
256        iter != nested_message_generators_.end(); ++iter) {
257     if ((*iter)->IncludesOneOfDefinition()) {
258       return true;
259     }
260   }
261 
262   return false;
263 }
264 
GenerateEnumHeader(io::Printer * printer)265 void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
266   for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
267        iter != enum_generators_.end(); ++iter) {
268     (*iter)->GenerateHeader(printer);
269   }
270 
271   for (vector<MessageGenerator*>::iterator iter =
272            nested_message_generators_.begin();
273        iter != nested_message_generators_.end(); ++iter) {
274     (*iter)->GenerateEnumHeader(printer);
275   }
276 }
277 
GenerateExtensionRegistrationSource(io::Printer * printer)278 void MessageGenerator::GenerateExtensionRegistrationSource(
279     io::Printer* printer) {
280   for (vector<ExtensionGenerator*>::iterator iter =
281            extension_generators_.begin();
282        iter != extension_generators_.end(); ++iter) {
283     (*iter)->GenerateRegistrationSource(printer);
284   }
285 
286   for (vector<MessageGenerator*>::iterator iter =
287            nested_message_generators_.begin();
288        iter != nested_message_generators_.end(); ++iter) {
289     (*iter)->GenerateExtensionRegistrationSource(printer);
290   }
291 }
292 
GenerateMessageHeader(io::Printer * printer)293 void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
294   // This a a map entry message, just recurse and do nothing directly.
295   if (IsMapEntryMessage(descriptor_)) {
296     for (vector<MessageGenerator*>::iterator iter =
297              nested_message_generators_.begin();
298          iter != nested_message_generators_.end(); ++iter) {
299       (*iter)->GenerateMessageHeader(printer);
300     }
301     return;
302   }
303 
304   printer->Print(
305       "#pragma mark - $classname$\n"
306       "\n",
307       "classname", class_name_);
308 
309   if (descriptor_->field_count()) {
310     scoped_array<const FieldDescriptor*> sorted_fields(
311         SortFieldsByNumber(descriptor_));
312 
313     printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
314                    "classname", class_name_);
315     printer->Indent();
316 
317     for (int i = 0; i < descriptor_->field_count(); i++) {
318       field_generators_.get(sorted_fields[i])
319           .GenerateFieldNumberConstant(printer);
320     }
321 
322     printer->Outdent();
323     printer->Print("};\n\n");
324   }
325 
326   for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
327        iter != oneof_generators_.end(); ++iter) {
328     (*iter)->GenerateCaseEnum(printer);
329   }
330 
331   string message_comments;
332   SourceLocation location;
333   if (descriptor_->GetSourceLocation(&location)) {
334     message_comments = BuildCommentsString(location);
335   } else {
336     message_comments = "";
337   }
338 
339   printer->Print(
340       "$comments$$deprecated_attribute$@interface $classname$ : GPBMessage\n\n",
341       "classname", class_name_,
342       "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, false, true),
343       "comments", message_comments);
344 
345   vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
346   for (int i = 0; i < descriptor_->field_count(); i++) {
347     const FieldDescriptor* field = descriptor_->field(i);
348     if (field->containing_oneof() != NULL) {
349       const int oneof_index = field->containing_oneof()->index();
350       if (!seen_oneofs[oneof_index]) {
351         seen_oneofs[oneof_index] = 1;
352         oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
353             printer);
354       }
355     }
356     field_generators_.get(field).GeneratePropertyDeclaration(printer);
357   }
358 
359   printer->Print("@end\n\n");
360 
361   for (int i = 0; i < descriptor_->field_count(); i++) {
362     field_generators_.get(descriptor_->field(i))
363         .GenerateCFunctionDeclarations(printer);
364   }
365 
366   if (!oneof_generators_.empty()) {
367     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
368          iter != oneof_generators_.end(); ++iter) {
369       (*iter)->GenerateClearFunctionDeclaration(printer);
370     }
371     printer->Print("\n");
372   }
373 
374   if (descriptor_->extension_count() > 0) {
375     printer->Print("@interface $classname$ (DynamicMethods)\n\n",
376                    "classname", class_name_);
377     for (vector<ExtensionGenerator*>::iterator iter =
378              extension_generators_.begin();
379          iter != extension_generators_.end(); ++iter) {
380       (*iter)->GenerateMembersHeader(printer);
381     }
382     printer->Print("@end\n\n");
383   }
384 
385   for (vector<MessageGenerator*>::iterator iter =
386            nested_message_generators_.begin();
387        iter != nested_message_generators_.end(); ++iter) {
388     (*iter)->GenerateMessageHeader(printer);
389   }
390 }
391 
GenerateSource(io::Printer * printer)392 void MessageGenerator::GenerateSource(io::Printer* printer) {
393   if (!IsMapEntryMessage(descriptor_)) {
394     printer->Print(
395         "#pragma mark - $classname$\n"
396         "\n",
397         "classname", class_name_);
398 
399     printer->Print("@implementation $classname$\n\n",
400                    "classname", class_name_);
401 
402     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
403          iter != oneof_generators_.end(); ++iter) {
404       (*iter)->GeneratePropertyImplementation(printer);
405     }
406 
407     for (int i = 0; i < descriptor_->field_count(); i++) {
408       field_generators_.get(descriptor_->field(i))
409           .GeneratePropertyImplementation(printer);
410     }
411 
412     scoped_array<const FieldDescriptor*> sorted_fields(
413         SortFieldsByNumber(descriptor_));
414     scoped_array<const FieldDescriptor*> size_order_fields(
415         SortFieldsByStorageSize(descriptor_));
416 
417     vector<const Descriptor::ExtensionRange*> sorted_extensions;
418     for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
419       sorted_extensions.push_back(descriptor_->extension_range(i));
420     }
421 
422     sort(sorted_extensions.begin(), sorted_extensions.end(),
423          ExtensionRangeOrdering());
424 
425     // Assign has bits:
426     // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
427     //    who needs has bits and assigning them.
428     // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
429     //    index that groups all the elements in the oneof.
430     size_t num_has_bits = field_generators_.CalculateHasBits();
431     size_t sizeof_has_storage = (num_has_bits + 31) / 32;
432     if (sizeof_has_storage == 0) {
433       // In the case where no field needs has bits, don't let the _has_storage_
434       // end up as zero length (zero length arrays are sort of a grey area
435       // since it has to be at the start of the struct). This also ensures a
436       // field with only oneofs keeps the required negative indices they need.
437       sizeof_has_storage = 1;
438     }
439     // Tell all the fields the oneof base.
440     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
441          iter != oneof_generators_.end(); ++iter) {
442       (*iter)->SetOneofIndexBase(sizeof_has_storage);
443     }
444     field_generators_.SetOneofIndexBase(sizeof_has_storage);
445     // sizeof_has_storage needs enough bits for the single fields that aren't in
446     // any oneof, and then one int32 for each oneof (to store the field number).
447     sizeof_has_storage += descriptor_->oneof_decl_count();
448 
449     printer->Print(
450         "\n"
451         "typedef struct $classname$__storage_ {\n"
452         "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
453         "classname", class_name_,
454         "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
455     printer->Indent();
456 
457     for (int i = 0; i < descriptor_->field_count(); i++) {
458       field_generators_.get(size_order_fields[i])
459           .GenerateFieldStorageDeclaration(printer);
460     }
461     printer->Outdent();
462 
463     printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
464 
465 
466     printer->Print(
467         "// This method is threadsafe because it is initially called\n"
468         "// in +initialize for each subclass.\n"
469         "+ (GPBDescriptor *)descriptor {\n"
470         "  static GPBDescriptor *descriptor = nil;\n"
471         "  if (!descriptor) {\n");
472 
473     TextFormatDecodeData text_format_decode_data;
474     bool has_fields = descriptor_->field_count() > 0;
475     bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
476     string field_description_type;
477     if (need_defaults) {
478       field_description_type = "GPBMessageFieldDescriptionWithDefault";
479     } else {
480       field_description_type = "GPBMessageFieldDescription";
481     }
482     if (has_fields) {
483       printer->Print(
484           "    static $field_description_type$ fields[] = {\n",
485           "field_description_type", field_description_type);
486       printer->Indent();
487       printer->Indent();
488       printer->Indent();
489       for (int i = 0; i < descriptor_->field_count(); ++i) {
490         const FieldGenerator& field_generator =
491             field_generators_.get(sorted_fields[i]);
492         field_generator.GenerateFieldDescription(printer, need_defaults);
493         if (field_generator.needs_textformat_name_support()) {
494           text_format_decode_data.AddString(sorted_fields[i]->number(),
495                                             field_generator.generated_objc_name(),
496                                             field_generator.raw_field_name());
497         }
498       }
499       printer->Outdent();
500       printer->Outdent();
501       printer->Outdent();
502       printer->Print(
503           "    };\n");
504     }
505 
506     map<string, string> vars;
507     vars["classname"] = class_name_;
508     vars["rootclassname"] = root_classname_;
509     vars["fields"] = has_fields ? "fields" : "NULL";
510     if (has_fields) {
511       vars["fields_count"] =
512           "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
513     } else {
514       vars["fields_count"] = "0";
515     }
516 
517     std::vector<string> init_flags;
518     if (need_defaults) {
519       init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
520     }
521     if (descriptor_->options().message_set_wire_format()) {
522       init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
523     }
524     vars["init_flags"] = BuildFlagsString(init_flags);
525 
526     printer->Print(
527         vars,
528         "    GPBDescriptor *localDescriptor =\n"
529         "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
530         "                                     rootClass:[$rootclassname$ class]\n"
531         "                                          file:$rootclassname$_FileDescriptor()\n"
532         "                                        fields:$fields$\n"
533         "                                    fieldCount:$fields_count$\n"
534         "                                   storageSize:sizeof($classname$__storage_)\n"
535         "                                         flags:$init_flags$];\n");
536     if (oneof_generators_.size() != 0) {
537       printer->Print(
538           "    static const char *oneofs[] = {\n");
539       for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
540            iter != oneof_generators_.end(); ++iter) {
541         printer->Print(
542             "      \"$name$\",\n",
543             "name", (*iter)->DescriptorName());
544       }
545       printer->Print(
546           "    };\n"
547           "    [localDescriptor setupOneofs:oneofs\n"
548           "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
549           "                   firstHasIndex:$first_has_index$];\n",
550           "first_has_index", oneof_generators_[0]->HasIndexAsString());
551     }
552     if (text_format_decode_data.num_entries() != 0) {
553       const string text_format_data_str(text_format_decode_data.Data());
554       printer->Print(
555           "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
556           "    static const char *extraTextFormatInfo =");
557       static const int kBytesPerLine = 40;  // allow for escaping
558       for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
559         printer->Print(
560             "\n        \"$data$\"",
561             "data", EscapeTrigraphs(
562                 CEscape(text_format_data_str.substr(i, kBytesPerLine))));
563       }
564       printer->Print(
565           ";\n"
566           "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
567           "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
568     }
569     if (sorted_extensions.size() != 0) {
570       printer->Print(
571           "    static const GPBExtensionRange ranges[] = {\n");
572       for (int i = 0; i < sorted_extensions.size(); i++) {
573         printer->Print("      { .start = $start$, .end = $end$ },\n",
574                        "start", SimpleItoa(sorted_extensions[i]->start),
575                        "end", SimpleItoa(sorted_extensions[i]->end));
576       }
577       printer->Print(
578           "    };\n"
579           "    [localDescriptor setupExtensionRanges:ranges\n"
580           "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
581     }
582     printer->Print(
583         "    NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
584         "    descriptor = localDescriptor;\n"
585         "  }\n"
586         "  return descriptor;\n"
587         "}\n\n"
588         "@end\n\n");
589 
590     for (int i = 0; i < descriptor_->field_count(); i++) {
591       field_generators_.get(descriptor_->field(i))
592           .GenerateCFunctionImplementations(printer);
593     }
594 
595     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
596          iter != oneof_generators_.end(); ++iter) {
597       (*iter)->GenerateClearFunctionImplementation(printer);
598     }
599   }
600 
601   for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
602        iter != enum_generators_.end(); ++iter) {
603     (*iter)->GenerateSource(printer);
604   }
605 
606   for (vector<MessageGenerator*>::iterator iter =
607            nested_message_generators_.begin();
608        iter != nested_message_generators_.end(); ++iter) {
609     (*iter)->GenerateSource(printer);
610   }
611 }
612 
613 }  // namespace objectivec
614 }  // namespace compiler
615 }  // namespace protobuf
616 }  // namespace google
617