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>
51 namespace objectivec {
54 struct FieldOrderingByNumber {
57 return a->number() <
b->number();
126 struct FieldOrderingByStorageSize {
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;
136 return a->number() <
b->number();
140 struct ExtensionRangeOrdering {
141 bool operator()(
const Descriptor::ExtensionRange* a,
142 const Descriptor::ExtensionRange*
b)
const {
143 return a->start <
b->start;
168 FieldOrderingByStorageSize());
176 : root_classname_(root_classname),
211 generator->GenerateStaticVariablesInitialization(printer);
215 generator->GenerateStaticVariablesInitialization(printer);
220 std::set<std::string>* fwd_decls) {
230 generator->DetermineForwardDeclarations(fwd_decls);
235 std::set<std::string>* fwd_decls) {
245 generator->DetermineObjectiveCClassDefinitions(fwd_decls);
249 generator->DetermineObjectiveCClassDefinitions(fwd_decls);
253 if (containing_descriptor != NULL) {
265 if (generator->IncludesOneOfDefinition()) {
275 generator->GenerateHeader(printer);
279 generator->GenerateEnumHeader(printer);
286 generator->GenerateRegistrationSource(printer);
290 generator->GenerateExtensionRegistrationSource(printer);
298 generator->GenerateMessageHeader(printer);
304 "#pragma mark - $classname$\n"
309 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
312 printer->Print(
"typedef GPB_ENUM($classname$_FieldNumber) {\n",
322 printer->Print(
"};\n\n");
326 generator->GenerateCaseEnum(printer);
334 message_comments =
"";
338 "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
341 "comments", message_comments);
348 const int oneof_index = oneof->index();
349 if (!seen_oneofs[oneof_index]) {
350 seen_oneofs[oneof_index] = 1;
358 printer->Print(
"@end\n\n");
367 generator->GenerateClearFunctionDeclaration(printer);
369 printer->Print(
"\n");
373 printer->Print(
"@interface $classname$ (DynamicMethods)\n\n",
376 generator->GenerateMembersHeader(printer);
378 printer->Print(
"@end\n\n");
382 generator->GenerateMessageHeader(printer);
389 "#pragma mark - $classname$\n"
396 "#pragma clang diagnostic push\n"
397 "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
401 printer->Print(
"@implementation $classname$\n\n",
405 generator->GeneratePropertyImplementation(printer);
413 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
415 std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
418 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
424 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
425 ExtensionRangeOrdering());
433 size_t sizeof_has_storage = (num_has_bits + 31) / 32;
434 if (sizeof_has_storage == 0) {
439 sizeof_has_storage = 1;
443 generator->SetOneofIndexBase(sizeof_has_storage);
452 "typedef struct $classname$__storage_ {\n"
453 " uint32_t _has_storage_[$sizeof_has_storage$];\n",
455 "sizeof_has_storage",
StrCat(sizeof_has_storage));
464 printer->Print(
"} $classname$__storage_;\n\n",
"classname",
class_name_);
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");
474 TextFormatDecodeData text_format_decode_data;
479 field_description_type =
"GPBMessageFieldDescriptionWithDefault";
481 field_description_type =
"GPBMessageFieldDescription";
487 "static $field_description_type$ fields[] = {\n",
488 "field_description_type", field_description_type);
491 const FieldGenerator& field_generator =
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());
507 std::map<std::string, std::string> vars;
510 vars[
"fields"] = has_fields ?
"fields" :
"NULL";
512 vars[
"fields_count"] =
513 "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type +
"))";
515 vars[
"fields_count"] =
"0";
518 std::vector<std::string> init_flags;
519 init_flags.push_back(
"GPBDescriptorInitializationFlag_UsesClassRefs");
520 init_flags.push_back(
"GPBDescriptorInitializationFlag_Proto3OptionalKnown");
522 init_flags.push_back(
"GPBDescriptorInitializationFlag_FieldsWithDefault");
525 init_flags.push_back(
"GPBDescriptorInitializationFlag_WireFormat");
532 " GPBDescriptor *localDescriptor =\n"
533 " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
534 " rootClass:[$rootclassname$ class]\n"
535 " file:$rootclassname$_FileDescriptor()\n"
537 " fieldCount:$fields_count$\n"
538 " storageSize:sizeof($classname$__storage_)\n"
539 " flags:$init_flags$];\n");
542 " static const char *oneofs[] = {\n");
544 printer->Print(
" \"$name$\",\n",
"name",
545 generator->DescriptorName());
549 " [localDescriptor setupOneofs:oneofs\n"
550 " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
551 " firstHasIndex:$first_has_index$];\n",
554 if (text_format_decode_data.num_entries() != 0) {
555 const std::string text_format_data_str(text_format_decode_data.Data());
557 "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
558 " static const char *extraTextFormatInfo =");
559 static const int kBytesPerLine = 40;
560 for (
int i = 0;
i < text_format_data_str.size();
i += kBytesPerLine) {
564 CEscape(text_format_data_str.substr(i, kBytesPerLine))));
568 " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
569 "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
571 if (!sorted_extensions.empty()) {
573 " static const GPBExtensionRange ranges[] = {\n");
574 for (
int i = 0;
i < sorted_extensions.size();
i++) {
575 printer->Print(
" { .start = $start$, .end = $end$ },\n",
577 "end",
StrCat(sorted_extensions[i]->
end));
581 " [localDescriptor setupExtensionRanges:ranges\n"
582 " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
588 " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
589 "parent_class_ref", parent_class_ref);
593 if (!suffix_added.empty()) {
595 " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
596 "suffix", suffix_added);
599 " #if defined(DEBUG) && DEBUG\n"
600 " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
602 " descriptor = localDescriptor;\n"
604 " return descriptor;\n"
610 "#pragma clang diagnostic pop\n"
620 generator->GenerateClearFunctionImplementation(printer);
625 generator->GenerateSource(printer);
629 generator->GenerateSource(printer);