• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::__anon4c9b7a200111::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::__anon4c9b7a200111::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::__anon4c9b7a200111::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 
GenerateEnumHeader(io::Printer * printer)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 
GenerateExtensionRegistrationSource(io::Printer * printer)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 
GenerateMessageHeader(io::Printer * printer)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 
GenerateSource(io::Printer * printer)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