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