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/compiler/objectivec/objectivec_message.h>
36 #include <google/protobuf/compiler/objectivec/objectivec_enum.h>
37 #include <google/protobuf/compiler/objectivec/objectivec_extension.h>
38 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
39 #include <google/protobuf/stubs/stl_util.h>
40 #include <google/protobuf/stubs/strutil.h>
41 #include <google/protobuf/io/printer.h>
42 #include <google/protobuf/io/coded_stream.h>
43 #include <google/protobuf/io/zero_copy_stream_impl.h>
44 #include <google/protobuf/wire_format.h>
45 #include <google/protobuf/wire_format_lite.h>
46 #include <google/protobuf/descriptor.pb.h>
47
48 namespace google {
49 namespace protobuf {
50 namespace compiler {
51 namespace objectivec {
52
53 namespace {
54 struct FieldOrderingByNumber {
operator ()google::protobuf::compiler::objectivec::__anon029b20720111::FieldOrderingByNumber55 inline bool operator()(const FieldDescriptor* a,
56 const FieldDescriptor* b) const {
57 return a->number() < b->number();
58 }
59 };
60
OrderGroupForFieldDescriptor(const FieldDescriptor * descriptor)61 int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
62 // The first item in the object structure is our uint32[] for has bits.
63 // We then want to order things to make the instances as small as
64 // possible. So we follow the has bits with:
65 // 1. Anything always 4 bytes - float, *32, enums
66 // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit
67 // builds and 4 bytes on 32bit builds.
68 // 3. Anything always 8 bytes - double, *64
69 //
70 // NOTE: Bools aren't listed, they were stored in the has bits.
71 //
72 // Why? Using 64bit builds as an example, this means worse case, we have
73 // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
74 // are wasted before the 4 byte values. Then if we have an odd number of
75 // those 4 byte values, the 8 byte values will be pushed down by 32bits to
76 // keep them aligned. But the structure will end 8 byte aligned, so no
77 // waste on the end. If you did the reverse order, you could waste 4 bytes
78 // before the first 8 byte value (after the has array), then a single
79 // bool on the end would need 7 bytes of padding to make the overall
80 // structure 8 byte aligned; so 11 bytes, wasted total.
81
82 // Anything repeated is a GPB*Array/NSArray, so pointer.
83 if (descriptor->is_repeated()) {
84 return 3;
85 }
86
87 switch (descriptor->type()) {
88 // All always 8 bytes.
89 case FieldDescriptor::TYPE_DOUBLE:
90 case FieldDescriptor::TYPE_INT64:
91 case FieldDescriptor::TYPE_SINT64:
92 case FieldDescriptor::TYPE_UINT64:
93 case FieldDescriptor::TYPE_SFIXED64:
94 case FieldDescriptor::TYPE_FIXED64:
95 return 4;
96
97 // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
98 // depending on the build architecture.
99 case FieldDescriptor::TYPE_GROUP:
100 case FieldDescriptor::TYPE_MESSAGE:
101 case FieldDescriptor::TYPE_STRING:
102 case FieldDescriptor::TYPE_BYTES:
103 return 3;
104
105 // All always 4 bytes (enums are int32s).
106 case FieldDescriptor::TYPE_FLOAT:
107 case FieldDescriptor::TYPE_INT32:
108 case FieldDescriptor::TYPE_SINT32:
109 case FieldDescriptor::TYPE_UINT32:
110 case FieldDescriptor::TYPE_SFIXED32:
111 case FieldDescriptor::TYPE_FIXED32:
112 case FieldDescriptor::TYPE_ENUM:
113 return 2;
114
115 // 0 bytes. Stored in the has bits.
116 case FieldDescriptor::TYPE_BOOL:
117 return 99; // End of the list (doesn't really matter).
118 }
119
120 // Some compilers report reaching end of function even though all cases of
121 // the enum are handed in the switch.
122 GOOGLE_LOG(FATAL) << "Can't get here.";
123 return 0;
124 }
125
126 struct FieldOrderingByStorageSize {
operator ()google::protobuf::compiler::objectivec::__anon029b20720111::FieldOrderingByStorageSize127 inline bool operator()(const FieldDescriptor* a,
128 const FieldDescriptor* b) const {
129 // Order by grouping.
130 const int order_group_a = OrderGroupForFieldDescriptor(a);
131 const int order_group_b = OrderGroupForFieldDescriptor(b);
132 if (order_group_a != order_group_b) {
133 return order_group_a < order_group_b;
134 }
135 // Within the group, order by field number (provides stable ordering).
136 return a->number() < b->number();
137 }
138 };
139
140 struct ExtensionRangeOrdering {
operator ()google::protobuf::compiler::objectivec::__anon029b20720111::ExtensionRangeOrdering141 bool operator()(const Descriptor::ExtensionRange* a,
142 const Descriptor::ExtensionRange* b) const {
143 return a->start < b->start;
144 }
145 };
146
147 // Sort the fields of the given Descriptor by number into a new[]'d array
148 // and return it.
SortFieldsByNumber(const Descriptor * descriptor)149 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
150 const FieldDescriptor** fields =
151 new const FieldDescriptor* [descriptor->field_count()];
152 for (int i = 0; i < descriptor->field_count(); i++) {
153 fields[i] = descriptor->field(i);
154 }
155 std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
156 return fields;
157 }
158
159 // Sort the fields of the given Descriptor by storage size into a new[]'d
160 // array and return it.
SortFieldsByStorageSize(const Descriptor * descriptor)161 const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
162 const FieldDescriptor** fields =
163 new const FieldDescriptor* [descriptor->field_count()];
164 for (int i = 0; i < descriptor->field_count(); i++) {
165 fields[i] = descriptor->field(i);
166 }
167 std::sort(fields, fields + descriptor->field_count(),
168 FieldOrderingByStorageSize());
169 return fields;
170 }
171 } // namespace
172
MessageGenerator(const std::string & root_classname,const Descriptor * descriptor,const Options & options)173 MessageGenerator::MessageGenerator(const std::string& root_classname,
174 const Descriptor* descriptor,
175 const Options& options)
176 : root_classname_(root_classname),
177 descriptor_(descriptor),
178 field_generators_(descriptor, options),
179 class_name_(ClassName(descriptor_)),
180 deprecated_attribute_(GetOptionalDeprecatedAttribute(
181 descriptor, descriptor->file(), false, true)) {
182 for (int i = 0; i < descriptor_->extension_count(); i++) {
183 extension_generators_.emplace_back(
184 new ExtensionGenerator(class_name_, descriptor_->extension(i)));
185 }
186
187 for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
188 OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
189 oneof_generators_.emplace_back(generator);
190 }
191
192 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
193 EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
194 enum_generators_.emplace_back(generator);
195 }
196
197 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
198 MessageGenerator* generator =
199 new MessageGenerator(root_classname_,
200 descriptor_->nested_type(i),
201 options);
202 nested_message_generators_.emplace_back(generator);
203 }
204 }
205
~MessageGenerator()206 MessageGenerator::~MessageGenerator() {}
207
GenerateStaticVariablesInitialization(io::Printer * printer)208 void MessageGenerator::GenerateStaticVariablesInitialization(
209 io::Printer* printer) {
210 for (const auto& generator : extension_generators_) {
211 generator->GenerateStaticVariablesInitialization(printer);
212 }
213
214 for (const auto& generator : nested_message_generators_) {
215 generator->GenerateStaticVariablesInitialization(printer);
216 }
217 }
218
DetermineForwardDeclarations(std::set<std::string> * fwd_decls)219 void MessageGenerator::DetermineForwardDeclarations(
220 std::set<std::string>* fwd_decls) {
221 if (!IsMapEntryMessage(descriptor_)) {
222 for (int i = 0; i < descriptor_->field_count(); i++) {
223 const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
224 field_generators_.get(fieldDescriptor)
225 .DetermineForwardDeclarations(fwd_decls);
226 }
227 }
228
229 for (const auto& generator : nested_message_generators_) {
230 generator->DetermineForwardDeclarations(fwd_decls);
231 }
232 }
233
DetermineObjectiveCClassDefinitions(std::set<std::string> * fwd_decls)234 void MessageGenerator::DetermineObjectiveCClassDefinitions(
235 std::set<std::string>* fwd_decls) {
236 if (!IsMapEntryMessage(descriptor_)) {
237 for (int i = 0; i < descriptor_->field_count(); i++) {
238 const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
239 field_generators_.get(fieldDescriptor)
240 .DetermineObjectiveCClassDefinitions(fwd_decls);
241 }
242 }
243
244 for (const auto& generator : extension_generators_) {
245 generator->DetermineObjectiveCClassDefinitions(fwd_decls);
246 }
247
248 for (const auto& generator : nested_message_generators_) {
249 generator->DetermineObjectiveCClassDefinitions(fwd_decls);
250 }
251
252 const Descriptor* containing_descriptor = descriptor_->containing_type();
253 if (containing_descriptor != NULL) {
254 std::string containing_class = ClassName(containing_descriptor);
255 fwd_decls->insert(ObjCClassDeclaration(containing_class));
256 }
257 }
258
IncludesOneOfDefinition() const259 bool MessageGenerator::IncludesOneOfDefinition() const {
260 if (!oneof_generators_.empty()) {
261 return true;
262 }
263
264 for (const auto& generator : nested_message_generators_) {
265 if (generator->IncludesOneOfDefinition()) {
266 return true;
267 }
268 }
269
270 return false;
271 }
272
GenerateEnumHeader(io::Printer * printer)273 void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
274 for (const auto& generator : enum_generators_) {
275 generator->GenerateHeader(printer);
276 }
277
278 for (const auto& generator : nested_message_generators_) {
279 generator->GenerateEnumHeader(printer);
280 }
281 }
282
GenerateExtensionRegistrationSource(io::Printer * printer)283 void MessageGenerator::GenerateExtensionRegistrationSource(
284 io::Printer* printer) {
285 for (const auto& generator : extension_generators_) {
286 generator->GenerateRegistrationSource(printer);
287 }
288
289 for (const auto& generator : nested_message_generators_) {
290 generator->GenerateExtensionRegistrationSource(printer);
291 }
292 }
293
GenerateMessageHeader(io::Printer * printer)294 void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
295 // This a a map entry message, just recurse and do nothing directly.
296 if (IsMapEntryMessage(descriptor_)) {
297 for (const auto& generator : nested_message_generators_) {
298 generator->GenerateMessageHeader(printer);
299 }
300 return;
301 }
302
303 printer->Print(
304 "#pragma mark - $classname$\n"
305 "\n",
306 "classname", class_name_);
307
308 if (descriptor_->field_count()) {
309 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
310 SortFieldsByNumber(descriptor_));
311
312 printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
313 "classname", class_name_);
314 printer->Indent();
315
316 for (int i = 0; i < descriptor_->field_count(); i++) {
317 field_generators_.get(sorted_fields[i])
318 .GenerateFieldNumberConstant(printer);
319 }
320
321 printer->Outdent();
322 printer->Print("};\n\n");
323 }
324
325 for (const auto& generator : oneof_generators_) {
326 generator->GenerateCaseEnum(printer);
327 }
328
329 std::string message_comments;
330 SourceLocation location;
331 if (descriptor_->GetSourceLocation(&location)) {
332 message_comments = BuildCommentsString(location, false);
333 } else {
334 message_comments = "";
335 }
336
337 printer->Print(
338 "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
339 "classname", class_name_,
340 "deprecated_attribute", deprecated_attribute_,
341 "comments", message_comments);
342
343 std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
344 for (int i = 0; i < descriptor_->field_count(); i++) {
345 const FieldDescriptor* field = descriptor_->field(i);
346 const OneofDescriptor *oneof = field->real_containing_oneof();
347 if (oneof) {
348 const int oneof_index = oneof->index();
349 if (!seen_oneofs[oneof_index]) {
350 seen_oneofs[oneof_index] = 1;
351 oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
352 printer);
353 }
354 }
355 field_generators_.get(field).GeneratePropertyDeclaration(printer);
356 }
357
358 printer->Print("@end\n\n");
359
360 for (int i = 0; i < descriptor_->field_count(); i++) {
361 field_generators_.get(descriptor_->field(i))
362 .GenerateCFunctionDeclarations(printer);
363 }
364
365 if (!oneof_generators_.empty()) {
366 for (const auto& generator : oneof_generators_) {
367 generator->GenerateClearFunctionDeclaration(printer);
368 }
369 printer->Print("\n");
370 }
371
372 if (descriptor_->extension_count() > 0) {
373 printer->Print("@interface $classname$ (DynamicMethods)\n\n",
374 "classname", class_name_);
375 for (const auto& generator : extension_generators_) {
376 generator->GenerateMembersHeader(printer);
377 }
378 printer->Print("@end\n\n");
379 }
380
381 for (const auto& generator : nested_message_generators_) {
382 generator->GenerateMessageHeader(printer);
383 }
384 }
385
GenerateSource(io::Printer * printer)386 void MessageGenerator::GenerateSource(io::Printer* printer) {
387 if (!IsMapEntryMessage(descriptor_)) {
388 printer->Print(
389 "#pragma mark - $classname$\n"
390 "\n",
391 "classname", class_name_);
392
393 if (!deprecated_attribute_.empty()) {
394 // No warnings when compiling the impl of this deprecated class.
395 printer->Print(
396 "#pragma clang diagnostic push\n"
397 "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
398 "\n");
399 }
400
401 printer->Print("@implementation $classname$\n\n",
402 "classname", class_name_);
403
404 for (const auto& generator : oneof_generators_) {
405 generator->GeneratePropertyImplementation(printer);
406 }
407
408 for (int i = 0; i < descriptor_->field_count(); i++) {
409 field_generators_.get(descriptor_->field(i))
410 .GeneratePropertyImplementation(printer);
411 }
412
413 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
414 SortFieldsByNumber(descriptor_));
415 std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
416 SortFieldsByStorageSize(descriptor_));
417
418 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
419 sorted_extensions.reserve(descriptor_->extension_range_count());
420 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
421 sorted_extensions.push_back(descriptor_->extension_range(i));
422 }
423
424 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
425 ExtensionRangeOrdering());
426
427 // Assign has bits:
428 // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
429 // who needs has bits and assigning them.
430 // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
431 // index that groups all the elements in the oneof.
432 size_t num_has_bits = field_generators_.CalculateHasBits();
433 size_t sizeof_has_storage = (num_has_bits + 31) / 32;
434 if (sizeof_has_storage == 0) {
435 // In the case where no field needs has bits, don't let the _has_storage_
436 // end up as zero length (zero length arrays are sort of a grey area
437 // since it has to be at the start of the struct). This also ensures a
438 // field with only oneofs keeps the required negative indices they need.
439 sizeof_has_storage = 1;
440 }
441 // Tell all the fields the oneof base.
442 for (const auto& generator : oneof_generators_) {
443 generator->SetOneofIndexBase(sizeof_has_storage);
444 }
445 field_generators_.SetOneofIndexBase(sizeof_has_storage);
446 // sizeof_has_storage needs enough bits for the single fields that aren't in
447 // any oneof, and then one int32 for each oneof (to store the field number).
448 sizeof_has_storage += oneof_generators_.size();
449
450 printer->Print(
451 "\n"
452 "typedef struct $classname$__storage_ {\n"
453 " uint32_t _has_storage_[$sizeof_has_storage$];\n",
454 "classname", class_name_,
455 "sizeof_has_storage", StrCat(sizeof_has_storage));
456 printer->Indent();
457
458 for (int i = 0; i < descriptor_->field_count(); i++) {
459 field_generators_.get(size_order_fields[i])
460 .GenerateFieldStorageDeclaration(printer);
461 }
462 printer->Outdent();
463
464 printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
465
466
467 printer->Print(
468 "// This method is threadsafe because it is initially called\n"
469 "// in +initialize for each subclass.\n"
470 "+ (GPBDescriptor *)descriptor {\n"
471 " static GPBDescriptor *descriptor = nil;\n"
472 " if (!descriptor) {\n");
473
474 TextFormatDecodeData text_format_decode_data;
475 bool has_fields = descriptor_->field_count() > 0;
476 bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
477 std::string field_description_type;
478 if (need_defaults) {
479 field_description_type = "GPBMessageFieldDescriptionWithDefault";
480 } else {
481 field_description_type = "GPBMessageFieldDescription";
482 }
483 if (has_fields) {
484 printer->Indent();
485 printer->Indent();
486 printer->Print(
487 "static $field_description_type$ fields[] = {\n",
488 "field_description_type", field_description_type);
489 printer->Indent();
490 for (int i = 0; i < descriptor_->field_count(); ++i) {
491 const FieldGenerator& field_generator =
492 field_generators_.get(sorted_fields[i]);
493 field_generator.GenerateFieldDescription(printer, need_defaults);
494 if (field_generator.needs_textformat_name_support()) {
495 text_format_decode_data.AddString(sorted_fields[i]->number(),
496 field_generator.generated_objc_name(),
497 field_generator.raw_field_name());
498 }
499 }
500 printer->Outdent();
501 printer->Print(
502 "};\n");
503 printer->Outdent();
504 printer->Outdent();
505 }
506
507 std::map<std::string, std::string> vars;
508 vars["classname"] = class_name_;
509 vars["rootclassname"] = root_classname_;
510 vars["fields"] = has_fields ? "fields" : "NULL";
511 if (has_fields) {
512 vars["fields_count"] =
513 "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
514 } else {
515 vars["fields_count"] = "0";
516 }
517
518 std::vector<std::string> init_flags;
519 init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
520 init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
521 if (need_defaults) {
522 init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
523 }
524 if (descriptor_->options().message_set_wire_format()) {
525 init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
526 }
527 vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
528 init_flags);
529
530 printer->Print(
531 vars,
532 " GPBDescriptor *localDescriptor =\n"
533 " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
534 " rootClass:[$rootclassname$ class]\n"
535 " file:$rootclassname$_FileDescriptor()\n"
536 " fields:$fields$\n"
537 " fieldCount:$fields_count$\n"
538 " storageSize:sizeof($classname$__storage_)\n"
539 " flags:$init_flags$];\n");
540 if (!oneof_generators_.empty()) {
541 printer->Print(
542 " static const char *oneofs[] = {\n");
543 for (const auto& generator : oneof_generators_) {
544 printer->Print(" \"$name$\",\n", "name",
545 generator->DescriptorName());
546 }
547 printer->Print(
548 " };\n"
549 " [localDescriptor setupOneofs:oneofs\n"
550 " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
551 " firstHasIndex:$first_has_index$];\n",
552 "first_has_index", oneof_generators_[0]->HasIndexAsString());
553 }
554 if (text_format_decode_data.num_entries() != 0) {
555 const std::string text_format_data_str(text_format_decode_data.Data());
556 printer->Print(
557 "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
558 " static const char *extraTextFormatInfo =");
559 static const int kBytesPerLine = 40; // allow for escaping
560 for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
561 printer->Print(
562 "\n \"$data$\"",
563 "data", EscapeTrigraphs(
564 CEscape(text_format_data_str.substr(i, kBytesPerLine))));
565 }
566 printer->Print(
567 ";\n"
568 " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
569 "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
570 }
571 if (!sorted_extensions.empty()) {
572 printer->Print(
573 " static const GPBExtensionRange ranges[] = {\n");
574 for (int i = 0; i < sorted_extensions.size(); i++) {
575 printer->Print(" { .start = $start$, .end = $end$ },\n",
576 "start", StrCat(sorted_extensions[i]->start),
577 "end", StrCat(sorted_extensions[i]->end));
578 }
579 printer->Print(
580 " };\n"
581 " [localDescriptor setupExtensionRanges:ranges\n"
582 " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
583 }
584 if (descriptor_->containing_type() != NULL) {
585 std::string containing_class = ClassName(descriptor_->containing_type());
586 std::string parent_class_ref = ObjCClass(containing_class);
587 printer->Print(
588 " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
589 "parent_class_ref", parent_class_ref);
590 }
591 std::string suffix_added;
592 ClassName(descriptor_, &suffix_added);
593 if (!suffix_added.empty()) {
594 printer->Print(
595 " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
596 "suffix", suffix_added);
597 }
598 printer->Print(
599 " #if defined(DEBUG) && DEBUG\n"
600 " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
601 " #endif // DEBUG\n"
602 " descriptor = localDescriptor;\n"
603 " }\n"
604 " return descriptor;\n"
605 "}\n\n"
606 "@end\n\n");
607
608 if (!deprecated_attribute_.empty()) {
609 printer->Print(
610 "#pragma clang diagnostic pop\n"
611 "\n");
612 }
613
614 for (int i = 0; i < descriptor_->field_count(); i++) {
615 field_generators_.get(descriptor_->field(i))
616 .GenerateCFunctionImplementations(printer);
617 }
618
619 for (const auto& generator : oneof_generators_) {
620 generator->GenerateClearFunctionImplementation(printer);
621 }
622 }
623
624 for (const auto& generator : enum_generators_) {
625 generator->GenerateSource(printer);
626 }
627
628 for (const auto& generator : nested_message_generators_) {
629 generator->GenerateSource(printer);
630 }
631 }
632
633 } // namespace objectivec
634 } // namespace compiler
635 } // namespace protobuf
636 } // namespace google
637