summaryrefslogtreecommitdiffstats
path: root/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2022-02-10 16:45:08 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:45:08 +0300
commit4e839db24a3bbc9f1c610c43d6faaaa99824dcca (patch)
tree506dac10f5df94fab310584ee51b24fc5a081c22 /contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc
parent2d37894b1b037cf24231090eda8589bbb44fb6fc (diff)
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc')
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc1272
1 files changed, 636 insertions, 636 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index 0f0087e5a3e..935af051587 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -1,636 +1,636 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <algorithm>
-#include <iostream>
-#include <sstream>
-
-#include <google/protobuf/compiler/objectivec/objectivec_message.h>
-#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
-#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.pb.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace objectivec {
-
-namespace {
-struct FieldOrderingByNumber {
- inline bool operator()(const FieldDescriptor* a,
- const FieldDescriptor* b) const {
- return a->number() < b->number();
- }
-};
-
-int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
- // The first item in the object structure is our uint32[] for has bits.
- // We then want to order things to make the instances as small as
- // possible. So we follow the has bits with:
- // 1. Anything always 4 bytes - float, *32, enums
- // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit
- // builds and 4 bytes on 32bit builds.
- // 3. Anything always 8 bytes - double, *64
- //
- // NOTE: Bools aren't listed, they were stored in the has bits.
- //
- // Why? Using 64bit builds as an example, this means worse case, we have
- // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
- // are wasted before the 4 byte values. Then if we have an odd number of
- // those 4 byte values, the 8 byte values will be pushed down by 32bits to
- // keep them aligned. But the structure will end 8 byte aligned, so no
- // waste on the end. If you did the reverse order, you could waste 4 bytes
- // before the first 8 byte value (after the has array), then a single
- // bool on the end would need 7 bytes of padding to make the overall
- // structure 8 byte aligned; so 11 bytes, wasted total.
-
- // Anything repeated is a GPB*Array/NSArray, so pointer.
- if (descriptor->is_repeated()) {
- return 3;
- }
-
- switch (descriptor->type()) {
- // All always 8 bytes.
- case FieldDescriptor::TYPE_DOUBLE:
- case FieldDescriptor::TYPE_INT64:
- case FieldDescriptor::TYPE_SINT64:
- case FieldDescriptor::TYPE_UINT64:
- case FieldDescriptor::TYPE_SFIXED64:
- case FieldDescriptor::TYPE_FIXED64:
- return 4;
-
- // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
- // depending on the build architecture.
- case FieldDescriptor::TYPE_GROUP:
- case FieldDescriptor::TYPE_MESSAGE:
- case FieldDescriptor::TYPE_STRING:
- case FieldDescriptor::TYPE_BYTES:
- return 3;
-
- // All always 4 bytes (enums are int32s).
- case FieldDescriptor::TYPE_FLOAT:
- case FieldDescriptor::TYPE_INT32:
- case FieldDescriptor::TYPE_SINT32:
- case FieldDescriptor::TYPE_UINT32:
- case FieldDescriptor::TYPE_SFIXED32:
- case FieldDescriptor::TYPE_FIXED32:
- case FieldDescriptor::TYPE_ENUM:
- return 2;
-
- // 0 bytes. Stored in the has bits.
- case FieldDescriptor::TYPE_BOOL:
- return 99; // End of the list (doesn't really matter).
- }
-
- // Some compilers report reaching end of function even though all cases of
- // the enum are handed in the switch.
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return 0;
-}
-
-struct FieldOrderingByStorageSize {
- inline bool operator()(const FieldDescriptor* a,
- const FieldDescriptor* b) const {
- // Order by grouping.
- const int order_group_a = OrderGroupForFieldDescriptor(a);
- const int order_group_b = OrderGroupForFieldDescriptor(b);
- if (order_group_a != order_group_b) {
- return order_group_a < order_group_b;
- }
- // Within the group, order by field number (provides stable ordering).
- return a->number() < b->number();
- }
-};
-
-struct ExtensionRangeOrdering {
- bool operator()(const Descriptor::ExtensionRange* a,
- const Descriptor::ExtensionRange* b) const {
- return a->start < b->start;
- }
-};
-
-// Sort the fields of the given Descriptor by number into a new[]'d array
-// and return it.
-const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
- const FieldDescriptor** fields =
- new const FieldDescriptor* [descriptor->field_count()];
- for (int i = 0; i < descriptor->field_count(); i++) {
- fields[i] = descriptor->field(i);
- }
- std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
- return fields;
-}
-
-// Sort the fields of the given Descriptor by storage size into a new[]'d
-// array and return it.
-const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
- const FieldDescriptor** fields =
- new const FieldDescriptor* [descriptor->field_count()];
- for (int i = 0; i < descriptor->field_count(); i++) {
- fields[i] = descriptor->field(i);
- }
- std::sort(fields, fields + descriptor->field_count(),
- FieldOrderingByStorageSize());
- return fields;
-}
-} // namespace
-
-MessageGenerator::MessageGenerator(const TProtoStringType& root_classname,
- const Descriptor* descriptor,
- const Options& options)
- : root_classname_(root_classname),
- descriptor_(descriptor),
- field_generators_(descriptor, options),
- class_name_(ClassName(descriptor_)),
- deprecated_attribute_(GetOptionalDeprecatedAttribute(
- descriptor, descriptor->file(), false, true)) {
- for (int i = 0; i < descriptor_->extension_count(); i++) {
- extension_generators_.emplace_back(
- new ExtensionGenerator(class_name_, descriptor_->extension(i)));
- }
-
- for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
- OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
- oneof_generators_.emplace_back(generator);
- }
-
- for (int i = 0; i < descriptor_->enum_type_count(); i++) {
- EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
- enum_generators_.emplace_back(generator);
- }
-
- for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- MessageGenerator* generator =
- new MessageGenerator(root_classname_,
- descriptor_->nested_type(i),
- options);
- nested_message_generators_.emplace_back(generator);
- }
-}
-
-MessageGenerator::~MessageGenerator() {}
-
-void MessageGenerator::GenerateStaticVariablesInitialization(
- io::Printer* printer) {
- for (const auto& generator : extension_generators_) {
- generator->GenerateStaticVariablesInitialization(printer);
- }
-
- for (const auto& generator : nested_message_generators_) {
- generator->GenerateStaticVariablesInitialization(printer);
- }
-}
-
-void MessageGenerator::DetermineForwardDeclarations(
- std::set<TProtoStringType>* fwd_decls) {
- if (!IsMapEntryMessage(descriptor_)) {
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
- field_generators_.get(fieldDescriptor)
- .DetermineForwardDeclarations(fwd_decls);
- }
- }
-
- for (const auto& generator : nested_message_generators_) {
- generator->DetermineForwardDeclarations(fwd_decls);
- }
-}
-
-void MessageGenerator::DetermineObjectiveCClassDefinitions(
- std::set<TProtoStringType>* fwd_decls) {
- if (!IsMapEntryMessage(descriptor_)) {
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
- field_generators_.get(fieldDescriptor)
- .DetermineObjectiveCClassDefinitions(fwd_decls);
- }
- }
-
- for (const auto& generator : extension_generators_) {
- generator->DetermineObjectiveCClassDefinitions(fwd_decls);
- }
-
- for (const auto& generator : nested_message_generators_) {
- generator->DetermineObjectiveCClassDefinitions(fwd_decls);
- }
-
- const Descriptor* containing_descriptor = descriptor_->containing_type();
- if (containing_descriptor != NULL) {
- TProtoStringType containing_class = ClassName(containing_descriptor);
- fwd_decls->insert(ObjCClassDeclaration(containing_class));
- }
-}
-
-bool MessageGenerator::IncludesOneOfDefinition() const {
- if (!oneof_generators_.empty()) {
- return true;
- }
-
- for (const auto& generator : nested_message_generators_) {
- if (generator->IncludesOneOfDefinition()) {
- return true;
- }
- }
-
- return false;
-}
-
-void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
- for (const auto& generator : enum_generators_) {
- generator->GenerateHeader(printer);
- }
-
- for (const auto& generator : nested_message_generators_) {
- generator->GenerateEnumHeader(printer);
- }
-}
-
-void MessageGenerator::GenerateExtensionRegistrationSource(
- io::Printer* printer) {
- for (const auto& generator : extension_generators_) {
- generator->GenerateRegistrationSource(printer);
- }
-
- for (const auto& generator : nested_message_generators_) {
- generator->GenerateExtensionRegistrationSource(printer);
- }
-}
-
-void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
- // This a a map entry message, just recurse and do nothing directly.
- if (IsMapEntryMessage(descriptor_)) {
- for (const auto& generator : nested_message_generators_) {
- generator->GenerateMessageHeader(printer);
- }
- return;
- }
-
- printer->Print(
- "#pragma mark - $classname$\n"
- "\n",
- "classname", class_name_);
-
- if (descriptor_->field_count()) {
- std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
- SortFieldsByNumber(descriptor_));
-
- printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
- "classname", class_name_);
- printer->Indent();
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(sorted_fields[i])
- .GenerateFieldNumberConstant(printer);
- }
-
- printer->Outdent();
- printer->Print("};\n\n");
- }
-
- for (const auto& generator : oneof_generators_) {
- generator->GenerateCaseEnum(printer);
- }
-
- TProtoStringType message_comments;
- SourceLocation location;
- if (descriptor_->GetSourceLocation(&location)) {
- message_comments = BuildCommentsString(location, false);
- } else {
- message_comments = "";
- }
-
- printer->Print(
- "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
- "classname", class_name_,
- "deprecated_attribute", deprecated_attribute_,
- "comments", message_comments);
-
- std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
- const OneofDescriptor* oneof = field->real_containing_oneof();
- if (oneof) {
- const int oneof_index = oneof->index();
- if (!seen_oneofs[oneof_index]) {
- seen_oneofs[oneof_index] = 1;
- oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
- printer);
- }
- }
- field_generators_.get(field).GeneratePropertyDeclaration(printer);
- }
-
- printer->Print("@end\n\n");
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i))
- .GenerateCFunctionDeclarations(printer);
- }
-
- if (!oneof_generators_.empty()) {
- for (const auto& generator : oneof_generators_) {
- generator->GenerateClearFunctionDeclaration(printer);
- }
- printer->Print("\n");
- }
-
- if (descriptor_->extension_count() > 0) {
- printer->Print("@interface $classname$ (DynamicMethods)\n\n",
- "classname", class_name_);
- for (const auto& generator : extension_generators_) {
- generator->GenerateMembersHeader(printer);
- }
- printer->Print("@end\n\n");
- }
-
- for (const auto& generator : nested_message_generators_) {
- generator->GenerateMessageHeader(printer);
- }
-}
-
-void MessageGenerator::GenerateSource(io::Printer* printer) {
- if (!IsMapEntryMessage(descriptor_)) {
- printer->Print(
- "#pragma mark - $classname$\n"
- "\n",
- "classname", class_name_);
-
- if (!deprecated_attribute_.empty()) {
- // No warnings when compiling the impl of this deprecated class.
- printer->Print(
- "#pragma clang diagnostic push\n"
- "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
- "\n");
- }
-
- printer->Print("@implementation $classname$\n\n",
- "classname", class_name_);
-
- for (const auto& generator : oneof_generators_) {
- generator->GeneratePropertyImplementation(printer);
- }
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i))
- .GeneratePropertyImplementation(printer);
- }
-
- std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
- SortFieldsByNumber(descriptor_));
- std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
- SortFieldsByStorageSize(descriptor_));
-
- std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
- sorted_extensions.reserve(descriptor_->extension_range_count());
- for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
- sorted_extensions.push_back(descriptor_->extension_range(i));
- }
-
- std::sort(sorted_extensions.begin(), sorted_extensions.end(),
- ExtensionRangeOrdering());
-
- // Assign has bits:
- // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
- // who needs has bits and assigning them.
- // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
- // index that groups all the elements in the oneof.
- size_t num_has_bits = field_generators_.CalculateHasBits();
- size_t sizeof_has_storage = (num_has_bits + 31) / 32;
- if (sizeof_has_storage == 0) {
- // In the case where no field needs has bits, don't let the _has_storage_
- // end up as zero length (zero length arrays are sort of a grey area
- // since it has to be at the start of the struct). This also ensures a
- // field with only oneofs keeps the required negative indices they need.
- sizeof_has_storage = 1;
- }
- // Tell all the fields the oneof base.
- for (const auto& generator : oneof_generators_) {
- generator->SetOneofIndexBase(sizeof_has_storage);
- }
- field_generators_.SetOneofIndexBase(sizeof_has_storage);
- // sizeof_has_storage needs enough bits for the single fields that aren't in
- // any oneof, and then one int32 for each oneof (to store the field number).
- sizeof_has_storage += oneof_generators_.size();
-
- printer->Print(
- "\n"
- "typedef struct $classname$__storage_ {\n"
- " uint32_t _has_storage_[$sizeof_has_storage$];\n",
- "classname", class_name_,
- "sizeof_has_storage", StrCat(sizeof_has_storage));
- printer->Indent();
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(size_order_fields[i])
- .GenerateFieldStorageDeclaration(printer);
- }
- printer->Outdent();
-
- printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
-
-
- printer->Print(
- "// This method is threadsafe because it is initially called\n"
- "// in +initialize for each subclass.\n"
- "+ (GPBDescriptor *)descriptor {\n"
- " static GPBDescriptor *descriptor = nil;\n"
- " if (!descriptor) {\n");
-
- TextFormatDecodeData text_format_decode_data;
- bool has_fields = descriptor_->field_count() > 0;
- bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
- TProtoStringType field_description_type;
- if (need_defaults) {
- field_description_type = "GPBMessageFieldDescriptionWithDefault";
- } else {
- field_description_type = "GPBMessageFieldDescription";
- }
- if (has_fields) {
- printer->Indent();
- printer->Indent();
- printer->Print(
- "static $field_description_type$ fields[] = {\n",
- "field_description_type", field_description_type);
- printer->Indent();
- for (int i = 0; i < descriptor_->field_count(); ++i) {
- const FieldGenerator& field_generator =
- field_generators_.get(sorted_fields[i]);
- field_generator.GenerateFieldDescription(printer, need_defaults);
- if (field_generator.needs_textformat_name_support()) {
- text_format_decode_data.AddString(sorted_fields[i]->number(),
- field_generator.generated_objc_name(),
- field_generator.raw_field_name());
- }
- }
- printer->Outdent();
- printer->Print(
- "};\n");
- printer->Outdent();
- printer->Outdent();
- }
-
- std::map<TProtoStringType, TProtoStringType> vars;
- vars["classname"] = class_name_;
- vars["rootclassname"] = root_classname_;
- vars["fields"] = has_fields ? "fields" : "NULL";
- if (has_fields) {
- vars["fields_count"] =
- "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
- } else {
- vars["fields_count"] = "0";
- }
-
- std::vector<TProtoStringType> init_flags;
- init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
- init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
- if (need_defaults) {
- init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
- }
- if (descriptor_->options().message_set_wire_format()) {
- init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
- }
- vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
- init_flags);
-
- printer->Print(
- vars,
- " GPBDescriptor *localDescriptor =\n"
- " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
- " rootClass:[$rootclassname$ class]\n"
- " file:$rootclassname$_FileDescriptor()\n"
- " fields:$fields$\n"
- " fieldCount:$fields_count$\n"
- " storageSize:sizeof($classname$__storage_)\n"
- " flags:$init_flags$];\n");
- if (!oneof_generators_.empty()) {
- printer->Print(
- " static const char *oneofs[] = {\n");
- for (const auto& generator : oneof_generators_) {
- printer->Print(" \"$name$\",\n", "name",
- generator->DescriptorName());
- }
- printer->Print(
- " };\n"
- " [localDescriptor setupOneofs:oneofs\n"
- " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
- " firstHasIndex:$first_has_index$];\n",
- "first_has_index", oneof_generators_[0]->HasIndexAsString());
- }
- if (text_format_decode_data.num_entries() != 0) {
- const TProtoStringType text_format_data_str(text_format_decode_data.Data());
- printer->Print(
- "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
- " static const char *extraTextFormatInfo =");
- static const int kBytesPerLine = 40; // allow for escaping
- for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
- printer->Print(
- "\n \"$data$\"",
- "data", EscapeTrigraphs(
- CEscape(text_format_data_str.substr(i, kBytesPerLine))));
- }
- printer->Print(
- ";\n"
- " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
- "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
- }
- if (!sorted_extensions.empty()) {
- printer->Print(
- " static const GPBExtensionRange ranges[] = {\n");
- for (int i = 0; i < sorted_extensions.size(); i++) {
- printer->Print(" { .start = $start$, .end = $end$ },\n",
- "start", StrCat(sorted_extensions[i]->start),
- "end", StrCat(sorted_extensions[i]->end));
- }
- printer->Print(
- " };\n"
- " [localDescriptor setupExtensionRanges:ranges\n"
- " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
- }
- if (descriptor_->containing_type() != NULL) {
- TProtoStringType containing_class = ClassName(descriptor_->containing_type());
- TProtoStringType parent_class_ref = ObjCClass(containing_class);
- printer->Print(
- " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
- "parent_class_ref", parent_class_ref);
- }
- TProtoStringType suffix_added;
- ClassName(descriptor_, &suffix_added);
- if (!suffix_added.empty()) {
- printer->Print(
- " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
- "suffix", suffix_added);
- }
- printer->Print(
- " #if defined(DEBUG) && DEBUG\n"
- " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
- " #endif // DEBUG\n"
- " descriptor = localDescriptor;\n"
- " }\n"
- " return descriptor;\n"
- "}\n\n"
- "@end\n\n");
-
- if (!deprecated_attribute_.empty()) {
- printer->Print(
- "#pragma clang diagnostic pop\n"
- "\n");
- }
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i))
- .GenerateCFunctionImplementations(printer);
- }
-
- for (const auto& generator : oneof_generators_) {
- generator->GenerateClearFunctionImplementation(printer);
- }
- }
-
- for (const auto& generator : enum_generators_) {
- generator->GenerateSource(printer);
- }
-
- for (const auto& generator : nested_message_generators_) {
- generator->GenerateSource(printer);
- }
-}
-
-} // namespace objectivec
-} // namespace compiler
-} // namespace protobuf
-} // namespace google
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#include <google/protobuf/compiler/objectivec/objectivec_message.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+struct FieldOrderingByNumber {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ return a->number() < b->number();
+ }
+};
+
+int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
+ // The first item in the object structure is our uint32[] for has bits.
+ // We then want to order things to make the instances as small as
+ // possible. So we follow the has bits with:
+ // 1. Anything always 4 bytes - float, *32, enums
+ // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit
+ // builds and 4 bytes on 32bit builds.
+ // 3. Anything always 8 bytes - double, *64
+ //
+ // NOTE: Bools aren't listed, they were stored in the has bits.
+ //
+ // Why? Using 64bit builds as an example, this means worse case, we have
+ // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
+ // are wasted before the 4 byte values. Then if we have an odd number of
+ // those 4 byte values, the 8 byte values will be pushed down by 32bits to
+ // keep them aligned. But the structure will end 8 byte aligned, so no
+ // waste on the end. If you did the reverse order, you could waste 4 bytes
+ // before the first 8 byte value (after the has array), then a single
+ // bool on the end would need 7 bytes of padding to make the overall
+ // structure 8 byte aligned; so 11 bytes, wasted total.
+
+ // Anything repeated is a GPB*Array/NSArray, so pointer.
+ if (descriptor->is_repeated()) {
+ return 3;
+ }
+
+ switch (descriptor->type()) {
+ // All always 8 bytes.
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_FIXED64:
+ return 4;
+
+ // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
+ // depending on the build architecture.
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ return 3;
+
+ // All always 4 bytes (enums are int32s).
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_ENUM:
+ return 2;
+
+ // 0 bytes. Stored in the has bits.
+ case FieldDescriptor::TYPE_BOOL:
+ return 99; // End of the list (doesn't really matter).
+ }
+
+ // Some compilers report reaching end of function even though all cases of
+ // the enum are handed in the switch.
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return 0;
+}
+
+struct FieldOrderingByStorageSize {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ // Order by grouping.
+ const int order_group_a = OrderGroupForFieldDescriptor(a);
+ const int order_group_b = OrderGroupForFieldDescriptor(b);
+ if (order_group_a != order_group_b) {
+ return order_group_a < order_group_b;
+ }
+ // Within the group, order by field number (provides stable ordering).
+ return a->number() < b->number();
+ }
+};
+
+struct ExtensionRangeOrdering {
+ bool operator()(const Descriptor::ExtensionRange* a,
+ const Descriptor::ExtensionRange* b) const {
+ return a->start < b->start;
+ }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
+ return fields;
+}
+
+// Sort the fields of the given Descriptor by storage size into a new[]'d
+// array and return it.
+const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ std::sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByStorageSize());
+ return fields;
+}
+} // namespace
+
+MessageGenerator::MessageGenerator(const TProtoStringType& root_classname,
+ const Descriptor* descriptor,
+ const Options& options)
+ : root_classname_(root_classname),
+ descriptor_(descriptor),
+ field_generators_(descriptor, options),
+ class_name_(ClassName(descriptor_)),
+ deprecated_attribute_(GetOptionalDeprecatedAttribute(
+ descriptor, descriptor->file(), false, true)) {
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ extension_generators_.emplace_back(
+ new ExtensionGenerator(class_name_, descriptor_->extension(i)));
+ }
+
+ for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+ OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
+ oneof_generators_.emplace_back(generator);
+ }
+
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
+ enum_generators_.emplace_back(generator);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ MessageGenerator* generator =
+ new MessageGenerator(root_classname_,
+ descriptor_->nested_type(i),
+ options);
+ nested_message_generators_.emplace_back(generator);
+ }
+}
+
+MessageGenerator::~MessageGenerator() {}
+
+void MessageGenerator::GenerateStaticVariablesInitialization(
+ io::Printer* printer) {
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateStaticVariablesInitialization(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateStaticVariablesInitialization(printer);
+ }
+}
+
+void MessageGenerator::DetermineForwardDeclarations(
+ std::set<TProtoStringType>* fwd_decls) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+ field_generators_.get(fieldDescriptor)
+ .DetermineForwardDeclarations(fwd_decls);
+ }
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->DetermineForwardDeclarations(fwd_decls);
+ }
+}
+
+void MessageGenerator::DetermineObjectiveCClassDefinitions(
+ std::set<TProtoStringType>* fwd_decls) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+ field_generators_.get(fieldDescriptor)
+ .DetermineObjectiveCClassDefinitions(fwd_decls);
+ }
+ }
+
+ for (const auto& generator : extension_generators_) {
+ generator->DetermineObjectiveCClassDefinitions(fwd_decls);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->DetermineObjectiveCClassDefinitions(fwd_decls);
+ }
+
+ const Descriptor* containing_descriptor = descriptor_->containing_type();
+ if (containing_descriptor != NULL) {
+ TProtoStringType containing_class = ClassName(containing_descriptor);
+ fwd_decls->insert(ObjCClassDeclaration(containing_class));
+ }
+}
+
+bool MessageGenerator::IncludesOneOfDefinition() const {
+ if (!oneof_generators_.empty()) {
+ return true;
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ if (generator->IncludesOneOfDefinition()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
+ for (const auto& generator : enum_generators_) {
+ generator->GenerateHeader(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateEnumHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateExtensionRegistrationSource(
+ io::Printer* printer) {
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateRegistrationSource(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateExtensionRegistrationSource(printer);
+ }
+}
+
+void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
+ // This a a map entry message, just recurse and do nothing directly.
+ if (IsMapEntryMessage(descriptor_)) {
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateMessageHeader(printer);
+ }
+ return;
+ }
+
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ if (descriptor_->field_count()) {
+ std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
+ "classname", class_name_);
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i])
+ .GenerateFieldNumberConstant(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("};\n\n");
+ }
+
+ for (const auto& generator : oneof_generators_) {
+ generator->GenerateCaseEnum(printer);
+ }
+
+ TProtoStringType message_comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ message_comments = BuildCommentsString(location, false);
+ } else {
+ message_comments = "";
+ }
+
+ printer->Print(
+ "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
+ "classname", class_name_,
+ "deprecated_attribute", deprecated_attribute_,
+ "comments", message_comments);
+
+ std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const OneofDescriptor* oneof = field->real_containing_oneof();
+ if (oneof) {
+ const int oneof_index = oneof->index();
+ if (!seen_oneofs[oneof_index]) {
+ seen_oneofs[oneof_index] = 1;
+ oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
+ printer);
+ }
+ }
+ field_generators_.get(field).GeneratePropertyDeclaration(printer);
+ }
+
+ printer->Print("@end\n\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateCFunctionDeclarations(printer);
+ }
+
+ if (!oneof_generators_.empty()) {
+ for (const auto& generator : oneof_generators_) {
+ generator->GenerateClearFunctionDeclaration(printer);
+ }
+ printer->Print("\n");
+ }
+
+ if (descriptor_->extension_count() > 0) {
+ printer->Print("@interface $classname$ (DynamicMethods)\n\n",
+ "classname", class_name_);
+ for (const auto& generator : extension_generators_) {
+ generator->GenerateMembersHeader(printer);
+ }
+ printer->Print("@end\n\n");
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateMessageHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateSource(io::Printer* printer) {
+ if (!IsMapEntryMessage(descriptor_)) {
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ if (!deprecated_attribute_.empty()) {
+ // No warnings when compiling the impl of this deprecated class.
+ printer->Print(
+ "#pragma clang diagnostic push\n"
+ "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
+ "\n");
+ }
+
+ printer->Print("@implementation $classname$\n\n",
+ "classname", class_name_);
+
+ for (const auto& generator : oneof_generators_) {
+ generator->GeneratePropertyImplementation(printer);
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GeneratePropertyImplementation(printer);
+ }
+
+ std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+ std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
+ SortFieldsByStorageSize(descriptor_));
+
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ sorted_extensions.reserve(descriptor_->extension_range_count());
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
+
+ // Assign has bits:
+ // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
+ // who needs has bits and assigning them.
+ // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+ // index that groups all the elements in the oneof.
+ size_t num_has_bits = field_generators_.CalculateHasBits();
+ size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+ if (sizeof_has_storage == 0) {
+ // In the case where no field needs has bits, don't let the _has_storage_
+ // end up as zero length (zero length arrays are sort of a grey area
+ // since it has to be at the start of the struct). This also ensures a
+ // field with only oneofs keeps the required negative indices they need.
+ sizeof_has_storage = 1;
+ }
+ // Tell all the fields the oneof base.
+ for (const auto& generator : oneof_generators_) {
+ generator->SetOneofIndexBase(sizeof_has_storage);
+ }
+ field_generators_.SetOneofIndexBase(sizeof_has_storage);
+ // sizeof_has_storage needs enough bits for the single fields that aren't in
+ // any oneof, and then one int32 for each oneof (to store the field number).
+ sizeof_has_storage += oneof_generators_.size();
+
+ printer->Print(
+ "\n"
+ "typedef struct $classname$__storage_ {\n"
+ " uint32_t _has_storage_[$sizeof_has_storage$];\n",
+ "classname", class_name_,
+ "sizeof_has_storage", StrCat(sizeof_has_storage));
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(size_order_fields[i])
+ .GenerateFieldStorageDeclaration(printer);
+ }
+ printer->Outdent();
+
+ printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
+
+
+ printer->Print(
+ "// This method is threadsafe because it is initially called\n"
+ "// in +initialize for each subclass.\n"
+ "+ (GPBDescriptor *)descriptor {\n"
+ " static GPBDescriptor *descriptor = nil;\n"
+ " if (!descriptor) {\n");
+
+ TextFormatDecodeData text_format_decode_data;
+ bool has_fields = descriptor_->field_count() > 0;
+ bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
+ TProtoStringType field_description_type;
+ if (need_defaults) {
+ field_description_type = "GPBMessageFieldDescriptionWithDefault";
+ } else {
+ field_description_type = "GPBMessageFieldDescription";
+ }
+ if (has_fields) {
+ printer->Indent();
+ printer->Indent();
+ printer->Print(
+ "static $field_description_type$ fields[] = {\n",
+ "field_description_type", field_description_type);
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); ++i) {
+ const FieldGenerator& field_generator =
+ field_generators_.get(sorted_fields[i]);
+ field_generator.GenerateFieldDescription(printer, need_defaults);
+ if (field_generator.needs_textformat_name_support()) {
+ text_format_decode_data.AddString(sorted_fields[i]->number(),
+ field_generator.generated_objc_name(),
+ field_generator.raw_field_name());
+ }
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n");
+ printer->Outdent();
+ printer->Outdent();
+ }
+
+ std::map<TProtoStringType, TProtoStringType> vars;
+ vars["classname"] = class_name_;
+ vars["rootclassname"] = root_classname_;
+ vars["fields"] = has_fields ? "fields" : "NULL";
+ if (has_fields) {
+ vars["fields_count"] =
+ "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
+ } else {
+ vars["fields_count"] = "0";
+ }
+
+ std::vector<TProtoStringType> init_flags;
+ init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
+ init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
+ if (need_defaults) {
+ init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
+ }
+ if (descriptor_->options().message_set_wire_format()) {
+ init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
+ }
+ vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+ init_flags);
+
+ printer->Print(
+ vars,
+ " GPBDescriptor *localDescriptor =\n"
+ " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+ " rootClass:[$rootclassname$ class]\n"
+ " file:$rootclassname$_FileDescriptor()\n"
+ " fields:$fields$\n"
+ " fieldCount:$fields_count$\n"
+ " storageSize:sizeof($classname$__storage_)\n"
+ " flags:$init_flags$];\n");
+ if (!oneof_generators_.empty()) {
+ printer->Print(
+ " static const char *oneofs[] = {\n");
+ for (const auto& generator : oneof_generators_) {
+ printer->Print(" \"$name$\",\n", "name",
+ generator->DescriptorName());
+ }
+ printer->Print(
+ " };\n"
+ " [localDescriptor setupOneofs:oneofs\n"
+ " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
+ " firstHasIndex:$first_has_index$];\n",
+ "first_has_index", oneof_generators_[0]->HasIndexAsString());
+ }
+ if (text_format_decode_data.num_entries() != 0) {
+ const TProtoStringType text_format_data_str(text_format_decode_data.Data());
+ printer->Print(
+ "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+ " static const char *extraTextFormatInfo =");
+ static const int kBytesPerLine = 40; // allow for escaping
+ for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
+ printer->Print(
+ "\n \"$data$\"",
+ "data", EscapeTrigraphs(
+ CEscape(text_format_data_str.substr(i, kBytesPerLine))));
+ }
+ printer->Print(
+ ";\n"
+ " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
+ "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
+ }
+ if (!sorted_extensions.empty()) {
+ printer->Print(
+ " static const GPBExtensionRange ranges[] = {\n");
+ for (int i = 0; i < sorted_extensions.size(); i++) {
+ printer->Print(" { .start = $start$, .end = $end$ },\n",
+ "start", StrCat(sorted_extensions[i]->start),
+ "end", StrCat(sorted_extensions[i]->end));
+ }
+ printer->Print(
+ " };\n"
+ " [localDescriptor setupExtensionRanges:ranges\n"
+ " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
+ }
+ if (descriptor_->containing_type() != NULL) {
+ TProtoStringType containing_class = ClassName(descriptor_->containing_type());
+ TProtoStringType parent_class_ref = ObjCClass(containing_class);
+ printer->Print(
+ " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
+ "parent_class_ref", parent_class_ref);
+ }
+ TProtoStringType suffix_added;
+ ClassName(descriptor_, &suffix_added);
+ if (!suffix_added.empty()) {
+ printer->Print(
+ " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
+ "suffix", suffix_added);
+ }
+ printer->Print(
+ " #if defined(DEBUG) && DEBUG\n"
+ " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
+ " #endif // DEBUG\n"
+ " descriptor = localDescriptor;\n"
+ " }\n"
+ " return descriptor;\n"
+ "}\n\n"
+ "@end\n\n");
+
+ if (!deprecated_attribute_.empty()) {
+ printer->Print(
+ "#pragma clang diagnostic pop\n"
+ "\n");
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateCFunctionImplementations(printer);
+ }
+
+ for (const auto& generator : oneof_generators_) {
+ generator->GenerateClearFunctionImplementation(printer);
+ }
+ }
+
+ for (const auto& generator : enum_generators_) {
+ generator->GenerateSource(printer);
+ }
+
+ for (const auto& generator : nested_message_generators_) {
+ generator->GenerateSource(printer);
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google