LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/compiler/objectivec - objectivec_message.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 1 263 0.4 %
Date: 2015-10-10 Functions: 2 14 14.3 %

          Line data    Source code
       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 {
      59           0 :   inline bool operator()(const FieldDescriptor* a,
      60           0 :                          const FieldDescriptor* b) const {
      61           0 :     return a->number() < b->number();
      62             :   }
      63             : };
      64             : 
      65           0 : 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. Bools (1 byte)
      70             :   //   2. Anything always 4 bytes - float, *32, enums
      71             :   //   3. Anything that is always a pointer (they will be 8 bytes on 64 bit
      72             :   //      builds and 4 bytes on 32bit builds.
      73             :   //   4. Anything always 8 bytes - double, *64
      74             :   //
      75             :   // Why? Using 64bit builds as an example, this means worse case, we have
      76             :   // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
      77             :   // are wasted before the 4 byte values. Then if we have an odd number of
      78             :   // those 4 byte values, the 8 byte values will be pushed down by 32bits to
      79             :   // keep them aligned. But the structure will end 8 byte aligned, so no
      80             :   // waste on the end. If you did the reverse order, you could waste 4 bytes
      81             :   // before the first 8 byte value (after the has array), then a single
      82             :   // bool on the end would need 7 bytes of padding to make the overall
      83             :   // structure 8 byte aligned; so 11 bytes, wasted total.
      84             : 
      85             :   // Anything repeated is a GPB*Array/NSArray, so pointer.
      86           0 :   if (descriptor->is_repeated()) {
      87             :     return 3;
      88             :   }
      89             : 
      90           0 :   switch (descriptor->type()) {
      91             :     // All always 8 bytes.
      92             :     case FieldDescriptor::TYPE_DOUBLE:
      93             :     case FieldDescriptor::TYPE_INT64:
      94             :     case FieldDescriptor::TYPE_SINT64:
      95             :     case FieldDescriptor::TYPE_UINT64:
      96             :     case FieldDescriptor::TYPE_SFIXED64:
      97             :     case FieldDescriptor::TYPE_FIXED64:
      98             :       return 4;
      99             : 
     100             :     // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
     101             :     // depending on the build architecture.
     102             :     case FieldDescriptor::TYPE_GROUP:
     103             :     case FieldDescriptor::TYPE_MESSAGE:
     104             :     case FieldDescriptor::TYPE_STRING:
     105             :     case FieldDescriptor::TYPE_BYTES:
     106           0 :       return 3;
     107             : 
     108             :     // All always 4 bytes (enums are int32s).
     109             :     case FieldDescriptor::TYPE_FLOAT:
     110             :     case FieldDescriptor::TYPE_INT32:
     111             :     case FieldDescriptor::TYPE_SINT32:
     112             :     case FieldDescriptor::TYPE_UINT32:
     113             :     case FieldDescriptor::TYPE_SFIXED32:
     114             :     case FieldDescriptor::TYPE_FIXED32:
     115             :     case FieldDescriptor::TYPE_ENUM:
     116           0 :       return 2;
     117             : 
     118             :     // 1 byte.
     119             :     case FieldDescriptor::TYPE_BOOL:
     120           0 :       return 1;
     121             :   }
     122             : 
     123             :   // Some compilers report reaching end of function even though all cases of
     124             :   // the enum are handed in the switch.
     125           0 :   GOOGLE_LOG(FATAL) << "Can't get here.";
     126           0 :   return 0;
     127             : }
     128             : 
     129             : struct FieldOrderingByStorageSize {
     130           0 :   inline bool operator()(const FieldDescriptor* a,
     131           0 :                          const FieldDescriptor* b) const {
     132             :     // Order by grouping.
     133           0 :     const int order_group_a = OrderGroupForFieldDescriptor(a);
     134           0 :     const int order_group_b = OrderGroupForFieldDescriptor(b);
     135           0 :     if (order_group_a != order_group_b) {
     136           0 :       return order_group_a < order_group_b;
     137             :     }
     138             :     // Within the group, order by field number (provides stable ordering).
     139           0 :     return a->number() < b->number();
     140             :   }
     141             : };
     142             : 
     143             : struct ExtensionRangeOrdering {
     144             :   bool operator()(const Descriptor::ExtensionRange* a,
     145             :                   const Descriptor::ExtensionRange* b) const {
     146             :     return a->start < b->start;
     147             :   }
     148             : };
     149             : 
     150             : // Sort the fields of the given Descriptor by number into a new[]'d array
     151             : // and return it.
     152           0 : const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
     153             :   const FieldDescriptor** fields =
     154           0 :       new const FieldDescriptor* [descriptor->field_count()];
     155           0 :   for (int i = 0; i < descriptor->field_count(); i++) {
     156           0 :     fields[i] = descriptor->field(i);
     157             :   }
     158           0 :   sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
     159           0 :   return fields;
     160             : }
     161             : 
     162             : // Sort the fields of the given Descriptor by storage size into a new[]'d
     163             : // array and return it.
     164           0 : const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
     165             :   const FieldDescriptor** fields =
     166           0 :       new const FieldDescriptor* [descriptor->field_count()];
     167           0 :   for (int i = 0; i < descriptor->field_count(); i++) {
     168           0 :     fields[i] = descriptor->field(i);
     169             :   }
     170           0 :   sort(fields, fields + descriptor->field_count(),
     171           0 :        FieldOrderingByStorageSize());
     172           0 :   return fields;
     173             : }
     174             : }  // namespace
     175             : 
     176           0 : MessageGenerator::MessageGenerator(const string& root_classname,
     177             :                                    const Descriptor* descriptor)
     178             :     : root_classname_(root_classname),
     179             :       descriptor_(descriptor),
     180             :       field_generators_(descriptor),
     181           0 :       class_name_(ClassName(descriptor_)) {
     182           0 :   for (int i = 0; i < descriptor_->extension_count(); i++) {
     183             :     extension_generators_.push_back(
     184           0 :         new ExtensionGenerator(class_name_, descriptor_->extension(i)));
     185             :   }
     186             : 
     187           0 :   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     188           0 :     OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
     189           0 :     oneof_generators_.push_back(generator);
     190             :   }
     191             : 
     192           0 :   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
     193           0 :     EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
     194           0 :     enum_generators_.push_back(generator);
     195             :   }
     196             : 
     197           0 :   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     198             :     MessageGenerator* generator =
     199           0 :         new MessageGenerator(root_classname_, descriptor_->nested_type(i));
     200           0 :     nested_message_generators_.push_back(generator);
     201             :   }
     202           0 : }
     203             : 
     204           0 : MessageGenerator::~MessageGenerator() {
     205             :   STLDeleteContainerPointers(extension_generators_.begin(),
     206           0 :                              extension_generators_.end());
     207           0 :   STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
     208             :   STLDeleteContainerPointers(nested_message_generators_.begin(),
     209           0 :                              nested_message_generators_.end());
     210             :   STLDeleteContainerPointers(oneof_generators_.begin(),
     211           0 :                              oneof_generators_.end());
     212           0 : }
     213             : 
     214           0 : void MessageGenerator::GenerateStaticVariablesInitialization(
     215             :     io::Printer* printer) {
     216           0 :   for (vector<ExtensionGenerator*>::iterator iter =
     217           0 :            extension_generators_.begin();
     218           0 :        iter != extension_generators_.end(); ++iter) {
     219           0 :     (*iter)->GenerateStaticVariablesInitialization(printer);
     220             :   }
     221             : 
     222           0 :   for (vector<MessageGenerator*>::iterator iter =
     223           0 :            nested_message_generators_.begin();
     224           0 :        iter != nested_message_generators_.end(); ++iter) {
     225           0 :     (*iter)->GenerateStaticVariablesInitialization(printer);
     226             :   }
     227           0 : }
     228             : 
     229           0 : void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
     230           0 :   if (!IsMapEntryMessage(descriptor_)) {
     231           0 :     for (int i = 0; i < descriptor_->field_count(); i++) {
     232           0 :       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
     233             :       // If it is a the field is repeated, the type will be and *Array, and we
     234             :       // don't need any forward decl.
     235           0 :       if (fieldDescriptor->is_repeated()) {
     236             :         continue;
     237             :       }
     238           0 :       field_generators_.get(fieldDescriptor)
     239           0 :           .DetermineForwardDeclarations(fwd_decls);
     240             :     }
     241             :   }
     242             : 
     243           0 :   for (vector<MessageGenerator*>::iterator iter =
     244           0 :            nested_message_generators_.begin();
     245           0 :        iter != nested_message_generators_.end(); ++iter) {
     246           0 :     (*iter)->DetermineForwardDeclarations(fwd_decls);
     247             :   }
     248           0 : }
     249             : 
     250           0 : void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
     251           0 :   for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
     252           0 :        iter != enum_generators_.end(); ++iter) {
     253           0 :     (*iter)->GenerateHeader(printer);
     254             :   }
     255             : 
     256           0 :   for (vector<MessageGenerator*>::iterator iter =
     257           0 :            nested_message_generators_.begin();
     258           0 :        iter != nested_message_generators_.end(); ++iter) {
     259           0 :     (*iter)->GenerateEnumHeader(printer);
     260             :   }
     261           0 : }
     262             : 
     263           0 : void MessageGenerator::GenerateExtensionRegistrationSource(
     264             :     io::Printer* printer) {
     265           0 :   for (vector<ExtensionGenerator*>::iterator iter =
     266           0 :            extension_generators_.begin();
     267           0 :        iter != extension_generators_.end(); ++iter) {
     268           0 :     (*iter)->GenerateRegistrationSource(printer);
     269             :   }
     270             : 
     271           0 :   for (vector<MessageGenerator*>::iterator iter =
     272           0 :            nested_message_generators_.begin();
     273           0 :        iter != nested_message_generators_.end(); ++iter) {
     274           0 :     (*iter)->GenerateExtensionRegistrationSource(printer);
     275             :   }
     276           0 : }
     277             : 
     278           0 : void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
     279             :   // This a a map entry message, just recurse and do nothing directly.
     280           0 :   if (IsMapEntryMessage(descriptor_)) {
     281           0 :     for (vector<MessageGenerator*>::iterator iter =
     282           0 :              nested_message_generators_.begin();
     283           0 :          iter != nested_message_generators_.end(); ++iter) {
     284           0 :       (*iter)->GenerateMessageHeader(printer);
     285             :     }
     286           0 :     return;
     287             :   }
     288             : 
     289             :   printer->Print(
     290             :       "#pragma mark - $classname$\n"
     291             :       "\n",
     292           0 :       "classname", class_name_);
     293             : 
     294           0 :   if (descriptor_->field_count()) {
     295             :     scoped_array<const FieldDescriptor*> sorted_fields(
     296           0 :         SortFieldsByNumber(descriptor_));
     297             : 
     298             :     printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
     299           0 :                    "classname", class_name_);
     300           0 :     printer->Indent();
     301             : 
     302           0 :     for (int i = 0; i < descriptor_->field_count(); i++) {
     303           0 :       field_generators_.get(sorted_fields[i])
     304           0 :           .GenerateFieldNumberConstant(printer);
     305             :     }
     306             : 
     307           0 :     printer->Outdent();
     308           0 :     printer->Print("};\n\n");
     309             :   }
     310             : 
     311           0 :   for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
     312           0 :        iter != oneof_generators_.end(); ++iter) {
     313           0 :     (*iter)->GenerateCaseEnum(printer);
     314             :   }
     315             : 
     316             :   string message_comments;
     317           0 :   SourceLocation location;
     318           0 :   if (descriptor_->GetSourceLocation(&location)) {
     319           0 :     message_comments = BuildCommentsString(location);
     320             :   } else {
     321             :     message_comments = "";
     322             :   }
     323             : 
     324             :   printer->Print(
     325             :       "$comments$@interface $classname$ : GPBMessage\n\n",
     326             :       "classname", class_name_,
     327           0 :       "comments", message_comments);
     328             : 
     329           0 :   vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
     330           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
     331           0 :     const FieldDescriptor* field = descriptor_->field(i);
     332           0 :     if (field->containing_oneof() != NULL) {
     333           0 :       const int oneof_index = field->containing_oneof()->index();
     334           0 :       if (!seen_oneofs[oneof_index]) {
     335           0 :         seen_oneofs[oneof_index] = 1;
     336           0 :         oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
     337           0 :             printer);
     338             :       }
     339             :     }
     340           0 :     field_generators_.get(field).GeneratePropertyDeclaration(printer);
     341             :   }
     342             : 
     343           0 :   printer->Print("@end\n\n");
     344             : 
     345           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
     346           0 :     field_generators_.get(descriptor_->field(i))
     347           0 :         .GenerateCFunctionDeclarations(printer);
     348             :   }
     349             : 
     350           0 :   if (!oneof_generators_.empty()) {
     351           0 :     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
     352           0 :          iter != oneof_generators_.end(); ++iter) {
     353           0 :       (*iter)->GenerateClearFunctionDeclaration(printer);
     354             :     }
     355           0 :     printer->Print("\n");
     356             :   }
     357             : 
     358           0 :   if (descriptor_->extension_count() > 0) {
     359             :     printer->Print("@interface $classname$ (DynamicMethods)\n\n",
     360           0 :                    "classname", class_name_);
     361           0 :     for (vector<ExtensionGenerator*>::iterator iter =
     362           0 :              extension_generators_.begin();
     363           0 :          iter != extension_generators_.end(); ++iter) {
     364           0 :       (*iter)->GenerateMembersHeader(printer);
     365             :     }
     366           0 :     printer->Print("@end\n\n");
     367             :   }
     368             : 
     369           0 :   for (vector<MessageGenerator*>::iterator iter =
     370           0 :            nested_message_generators_.begin();
     371           0 :        iter != nested_message_generators_.end(); ++iter) {
     372           0 :     (*iter)->GenerateMessageHeader(printer);
     373             :   }
     374             : }
     375             : 
     376           0 : void MessageGenerator::GenerateSource(io::Printer* printer) {
     377           0 :   if (!IsMapEntryMessage(descriptor_)) {
     378             :     printer->Print(
     379             :         "#pragma mark - $classname$\n"
     380             :         "\n",
     381           0 :         "classname", class_name_);
     382             : 
     383             :     printer->Print("@implementation $classname$\n\n",
     384           0 :                    "classname", class_name_);
     385             : 
     386           0 :     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
     387           0 :          iter != oneof_generators_.end(); ++iter) {
     388           0 :       (*iter)->GeneratePropertyImplementation(printer);
     389             :     }
     390             : 
     391           0 :     for (int i = 0; i < descriptor_->field_count(); i++) {
     392           0 :       field_generators_.get(descriptor_->field(i))
     393           0 :           .GeneratePropertyImplementation(printer);
     394             :     }
     395             : 
     396             :     scoped_array<const FieldDescriptor*> sorted_fields(
     397           0 :         SortFieldsByNumber(descriptor_));
     398             :     scoped_array<const FieldDescriptor*> size_order_fields(
     399           0 :         SortFieldsByStorageSize(descriptor_));
     400             : 
     401             :     vector<const Descriptor::ExtensionRange*> sorted_extensions;
     402           0 :     for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     403           0 :       sorted_extensions.push_back(descriptor_->extension_range(i));
     404             :     }
     405             : 
     406             :     sort(sorted_extensions.begin(), sorted_extensions.end(),
     407           0 :          ExtensionRangeOrdering());
     408             : 
     409             :     // TODO(thomasvl): Finish optimizing has bit. The current behavior is as
     410             :     // follows:
     411             :     // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index
     412             :     //    to the field's index in the list of fields.
     413             :     // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to
     414             :     //    GPBNoHasBit because repeated fields & map<> fields don't use the has
     415             :     //    bit.
     416             :     // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
     417             :     //    index that groups all the elements on of the oneof.
     418             :     // So in has_storage, we need enough bits for the single fields that aren't
     419             :     // in any oneof, and then one int32 for each oneof (to store the field
     420             :     // number).  So we could save a little space by not using the field's index
     421             :     // and instead make a second pass only assigning indexes for the fields
     422             :     // that would need it.  The only savings would come when messages have over
     423             :     // a multiple of 32 fields with some number being repeated or in oneofs to
     424             :     // drop the count below that 32 multiple; so it hasn't seemed worth doing
     425             :     // at the moment.
     426           0 :     size_t num_has_bits = descriptor_->field_count();
     427           0 :     size_t sizeof_has_storage = (num_has_bits + 31) / 32;
     428             :     // Tell all the fields the oneof base.
     429           0 :     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
     430           0 :          iter != oneof_generators_.end(); ++iter) {
     431           0 :       (*iter)->SetOneofIndexBase(sizeof_has_storage);
     432             :     }
     433           0 :     field_generators_.SetOneofIndexBase(sizeof_has_storage);
     434             :     // Add an int32 for each oneof to store which is set.
     435           0 :     sizeof_has_storage += descriptor_->oneof_decl_count();
     436             : 
     437             :     printer->Print(
     438             :         "\n"
     439             :         "typedef struct $classname$__storage_ {\n"
     440             :         "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
     441             :         "classname", class_name_,
     442           0 :         "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
     443           0 :     printer->Indent();
     444             : 
     445           0 :     for (int i = 0; i < descriptor_->field_count(); i++) {
     446           0 :       field_generators_.get(size_order_fields[i])
     447           0 :           .GenerateFieldStorageDeclaration(printer);
     448             :     }
     449           0 :     printer->Outdent();
     450             : 
     451           0 :     printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
     452             : 
     453             : 
     454             :     printer->Print(
     455             :         "// This method is threadsafe because it is initially called\n"
     456             :         "// in +initialize for each subclass.\n"
     457             :         "+ (GPBDescriptor *)descriptor {\n"
     458             :         "  static GPBDescriptor *descriptor = nil;\n"
     459           0 :         "  if (!descriptor) {\n");
     460             : 
     461           0 :     bool has_oneofs = oneof_generators_.size();
     462           0 :     if (has_oneofs) {
     463             :       printer->Print(
     464           0 :           "    static GPBMessageOneofDescription oneofs[] = {\n");
     465           0 :       printer->Indent();
     466           0 :       printer->Indent();
     467           0 :       printer->Indent();
     468           0 :       for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
     469           0 :            iter != oneof_generators_.end(); ++iter) {
     470           0 :         (*iter)->GenerateDescription(printer);
     471             :       }
     472           0 :       printer->Outdent();
     473           0 :       printer->Outdent();
     474           0 :       printer->Outdent();
     475             :       printer->Print(
     476           0 :           "    };\n");
     477             :     }
     478             : 
     479             :     TextFormatDecodeData text_format_decode_data;
     480           0 :     bool has_fields = descriptor_->field_count() > 0;
     481           0 :     if (has_fields) {
     482             :       // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription()
     483             :       // wraps the fieldOptions's value of this structure in an CPP gate so
     484             :       // they can be compiled away; but that still results in a const char* in
     485             :       // the structure for a NULL pointer for every message field.  If the
     486             :       // fieldOptions are moved to a separate payload like the TextFormat extra
     487             :       // data is, then it would shrink that static data shrinking the binaries
     488             :       // a little more.
     489             :       // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the
     490             :       // structure because primitive types are always zero.  If we add a second
     491             :       // structure and a different initializer, we can avoid the wasted static
     492             :       // storage for every field in a proto3 message.
     493             :       printer->Print(
     494           0 :           "    static GPBMessageFieldDescription fields[] = {\n");
     495           0 :       printer->Indent();
     496           0 :       printer->Indent();
     497           0 :       printer->Indent();
     498           0 :       for (int i = 0; i < descriptor_->field_count(); ++i) {
     499             :         const FieldGenerator& field_generator =
     500           0 :             field_generators_.get(sorted_fields[i]);
     501           0 :         field_generator.GenerateFieldDescription(printer);
     502           0 :         if (field_generator.needs_textformat_name_support()) {
     503           0 :           text_format_decode_data.AddString(sorted_fields[i]->number(),
     504             :                                             field_generator.generated_objc_name(),
     505           0 :                                             field_generator.raw_field_name());
     506             :         }
     507             :       }
     508           0 :       printer->Outdent();
     509           0 :       printer->Outdent();
     510           0 :       printer->Outdent();
     511             :       printer->Print(
     512           0 :           "    };\n");
     513             :     }
     514             : 
     515           0 :     bool has_enums = enum_generators_.size();
     516           0 :     if (has_enums) {
     517             :       printer->Print(
     518           0 :           "    static GPBMessageEnumDescription enums[] = {\n");
     519           0 :       printer->Indent();
     520           0 :       printer->Indent();
     521           0 :       printer->Indent();
     522           0 :       for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
     523           0 :            iter != enum_generators_.end(); ++iter) {
     524             :         printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n",
     525           0 :                        "name", (*iter)->name());
     526             :       }
     527           0 :       printer->Outdent();
     528           0 :       printer->Outdent();
     529           0 :       printer->Outdent();
     530             :       printer->Print(
     531           0 :           "    };\n");
     532             :     }
     533             : 
     534           0 :     bool has_extensions = sorted_extensions.size();
     535           0 :     if (has_extensions) {
     536             :       printer->Print(
     537           0 :           "    static GPBExtensionRange ranges[] = {\n");
     538           0 :       printer->Indent();
     539           0 :       printer->Indent();
     540           0 :       printer->Indent();
     541           0 :       for (int i = 0; i < sorted_extensions.size(); i++) {
     542             :         printer->Print("{ .start = $start$, .end = $end$ },\n",
     543           0 :                        "start", SimpleItoa(sorted_extensions[i]->start),
     544           0 :                        "end", SimpleItoa(sorted_extensions[i]->end));
     545             :       }
     546           0 :       printer->Outdent();
     547           0 :       printer->Outdent();
     548           0 :       printer->Outdent();
     549             :       printer->Print(
     550           0 :           "    };\n");
     551             :     }
     552             : 
     553             :     map<string, string> vars;
     554           0 :     vars["classname"] = class_name_;
     555           0 :     vars["rootclassname"] = root_classname_;
     556           0 :     vars["fields"] = has_fields ? "fields" : "NULL";
     557           0 :     vars["fields_count"] =
     558             :         has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
     559           0 :     vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
     560           0 :     vars["oneof_count"] =
     561             :         has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
     562           0 :     vars["enums"] = has_enums ? "enums" : "NULL";
     563           0 :     vars["enum_count"] =
     564             :         has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0";
     565           0 :     vars["ranges"] = has_extensions ? "ranges" : "NULL";
     566           0 :     vars["range_count"] =
     567             :         has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0";
     568           0 :     vars["wireformat"] =
     569           0 :         descriptor_->options().message_set_wire_format() ? "YES" : "NO";
     570             : 
     571           0 :     if (text_format_decode_data.num_entries() == 0) {
     572             :       printer->Print(
     573             :           vars,
     574             :           "    GPBDescriptor *localDescriptor =\n"
     575             :           "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
     576             :           "                                     rootClass:[$rootclassname$ class]\n"
     577             :           "                                          file:$rootclassname$_FileDescriptor()\n"
     578             :           "                                        fields:$fields$\n"
     579             :           "                                    fieldCount:$fields_count$\n"
     580             :           "                                        oneofs:$oneofs$\n"
     581             :           "                                    oneofCount:$oneof_count$\n"
     582             :           "                                         enums:$enums$\n"
     583             :           "                                     enumCount:$enum_count$\n"
     584             :           "                                        ranges:$ranges$\n"
     585             :           "                                    rangeCount:$range_count$\n"
     586             :           "                                   storageSize:sizeof($classname$__storage_)\n"
     587           0 :           "                                    wireFormat:$wireformat$];\n");
     588             :     } else {
     589           0 :       vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data());
     590             :       printer->Print(
     591             :           vars,
     592             :           "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
     593             :           "    const char *extraTextFormatInfo = NULL;\n"
     594             :           "#else\n"
     595             :           "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
     596             :           "#endif  // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
     597             :           "    GPBDescriptor *localDescriptor =\n"
     598             :           "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
     599             :           "                                     rootClass:[$rootclassname$ class]\n"
     600             :           "                                          file:$rootclassname$_FileDescriptor()\n"
     601             :           "                                        fields:$fields$\n"
     602             :           "                                    fieldCount:$fields_count$\n"
     603             :           "                                        oneofs:$oneofs$\n"
     604             :           "                                    oneofCount:$oneof_count$\n"
     605             :           "                                         enums:$enums$\n"
     606             :           "                                     enumCount:$enum_count$\n"
     607             :           "                                        ranges:$ranges$\n"
     608             :           "                                    rangeCount:$range_count$\n"
     609             :           "                                   storageSize:sizeof($classname$__storage_)\n"
     610             :           "                                    wireFormat:$wireformat$\n"
     611           0 :           "                           extraTextFormatInfo:extraTextFormatInfo];\n");
     612             :       }
     613             :       printer->Print(
     614             :           "    NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
     615             :           "    descriptor = localDescriptor;\n"
     616             :           "  }\n"
     617             :           "  return descriptor;\n"
     618             :           "}\n\n"
     619           0 :           "@end\n\n");
     620             : 
     621           0 :     for (int i = 0; i < descriptor_->field_count(); i++) {
     622           0 :       field_generators_.get(descriptor_->field(i))
     623           0 :           .GenerateCFunctionImplementations(printer);
     624             :     }
     625             : 
     626           0 :     for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
     627           0 :          iter != oneof_generators_.end(); ++iter) {
     628           0 :       (*iter)->GenerateClearFunctionImplementation(printer);
     629             :     }
     630             :   }
     631             : 
     632           0 :   for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
     633           0 :        iter != enum_generators_.end(); ++iter) {
     634           0 :     (*iter)->GenerateSource(printer);
     635             :   }
     636             : 
     637           0 :   for (vector<MessageGenerator*>::iterator iter =
     638           0 :            nested_message_generators_.begin();
     639           0 :        iter != nested_message_generators_.end(); ++iter) {
     640           0 :     (*iter)->GenerateSource(printer);
     641             :   }
     642           0 : }
     643             : 
     644             : }  // namespace objectivec
     645             : }  // namespace compiler
     646             : }  // namespace protobuf
     647          51 : }  // namespace google

Generated by: LCOV version 1.10