| Index: third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..32671d42013dffc73eae1df58ba80551668e3ba2
|
| --- /dev/null
|
| +++ b/third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc
|
| @@ -0,0 +1,647 @@
|
| +// 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/stubs/hash.h>
|
| +#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_inl.h>
|
| +#include <google/protobuf/descriptor.pb.h>
|
| +
|
| +namespace google {
|
| +namespace protobuf {
|
| +namespace compiler {
|
| +namespace objectivec {
|
| +
|
| +using internal::WireFormat;
|
| +using internal::WireFormatLite;
|
| +
|
| +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. Bools (1 byte)
|
| + // 2. Anything always 4 bytes - float, *32, enums
|
| + // 3. Anything that is always a pointer (they will be 8 bytes on 64 bit
|
| + // builds and 4 bytes on 32bit builds.
|
| + // 4. Anything always 8 bytes - double, *64
|
| + //
|
| + // 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;
|
| +
|
| + // 1 byte.
|
| + case FieldDescriptor::TYPE_BOOL:
|
| + return 1;
|
| + }
|
| +
|
| + // 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);
|
| + }
|
| + 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);
|
| + }
|
| + sort(fields, fields + descriptor->field_count(),
|
| + FieldOrderingByStorageSize());
|
| + return fields;
|
| +}
|
| +} // namespace
|
| +
|
| +MessageGenerator::MessageGenerator(const string& root_classname,
|
| + const Descriptor* descriptor)
|
| + : root_classname_(root_classname),
|
| + descriptor_(descriptor),
|
| + field_generators_(descriptor),
|
| + class_name_(ClassName(descriptor_)) {
|
| + for (int i = 0; i < descriptor_->extension_count(); i++) {
|
| + extension_generators_.push_back(
|
| + new ExtensionGenerator(class_name_, descriptor_->extension(i)));
|
| + }
|
| +
|
| + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
|
| + OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
|
| + oneof_generators_.push_back(generator);
|
| + }
|
| +
|
| + for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
| + EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
|
| + enum_generators_.push_back(generator);
|
| + }
|
| +
|
| + for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
| + MessageGenerator* generator =
|
| + new MessageGenerator(root_classname_, descriptor_->nested_type(i));
|
| + nested_message_generators_.push_back(generator);
|
| + }
|
| +}
|
| +
|
| +MessageGenerator::~MessageGenerator() {
|
| + STLDeleteContainerPointers(extension_generators_.begin(),
|
| + extension_generators_.end());
|
| + STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
|
| + STLDeleteContainerPointers(nested_message_generators_.begin(),
|
| + nested_message_generators_.end());
|
| + STLDeleteContainerPointers(oneof_generators_.begin(),
|
| + oneof_generators_.end());
|
| +}
|
| +
|
| +void MessageGenerator::GenerateStaticVariablesInitialization(
|
| + io::Printer* printer) {
|
| + for (vector<ExtensionGenerator*>::iterator iter =
|
| + extension_generators_.begin();
|
| + iter != extension_generators_.end(); ++iter) {
|
| + (*iter)->GenerateStaticVariablesInitialization(printer);
|
| + }
|
| +
|
| + for (vector<MessageGenerator*>::iterator iter =
|
| + nested_message_generators_.begin();
|
| + iter != nested_message_generators_.end(); ++iter) {
|
| + (*iter)->GenerateStaticVariablesInitialization(printer);
|
| + }
|
| +}
|
| +
|
| +void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
|
| + if (!IsMapEntryMessage(descriptor_)) {
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
|
| + // If it is a the field is repeated, the type will be and *Array, and we
|
| + // don't need any forward decl.
|
| + if (fieldDescriptor->is_repeated()) {
|
| + continue;
|
| + }
|
| + field_generators_.get(fieldDescriptor)
|
| + .DetermineForwardDeclarations(fwd_decls);
|
| + }
|
| + }
|
| +
|
| + for (vector<MessageGenerator*>::iterator iter =
|
| + nested_message_generators_.begin();
|
| + iter != nested_message_generators_.end(); ++iter) {
|
| + (*iter)->DetermineForwardDeclarations(fwd_decls);
|
| + }
|
| +}
|
| +
|
| +void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
|
| + for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
|
| + iter != enum_generators_.end(); ++iter) {
|
| + (*iter)->GenerateHeader(printer);
|
| + }
|
| +
|
| + for (vector<MessageGenerator*>::iterator iter =
|
| + nested_message_generators_.begin();
|
| + iter != nested_message_generators_.end(); ++iter) {
|
| + (*iter)->GenerateEnumHeader(printer);
|
| + }
|
| +}
|
| +
|
| +void MessageGenerator::GenerateExtensionRegistrationSource(
|
| + io::Printer* printer) {
|
| + for (vector<ExtensionGenerator*>::iterator iter =
|
| + extension_generators_.begin();
|
| + iter != extension_generators_.end(); ++iter) {
|
| + (*iter)->GenerateRegistrationSource(printer);
|
| + }
|
| +
|
| + for (vector<MessageGenerator*>::iterator iter =
|
| + nested_message_generators_.begin();
|
| + iter != nested_message_generators_.end(); ++iter) {
|
| + (*iter)->GenerateExtensionRegistrationSource(printer);
|
| + }
|
| +}
|
| +
|
| +void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
|
| + // This a a map entry message, just recurse and do nothing directly.
|
| + if (IsMapEntryMessage(descriptor_)) {
|
| + for (vector<MessageGenerator*>::iterator iter =
|
| + nested_message_generators_.begin();
|
| + iter != nested_message_generators_.end(); ++iter) {
|
| + (*iter)->GenerateMessageHeader(printer);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + printer->Print(
|
| + "#pragma mark - $classname$\n"
|
| + "\n",
|
| + "classname", class_name_);
|
| +
|
| + if (descriptor_->field_count()) {
|
| + scoped_array<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 (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
|
| + iter != oneof_generators_.end(); ++iter) {
|
| + (*iter)->GenerateCaseEnum(printer);
|
| + }
|
| +
|
| + string message_comments;
|
| + SourceLocation location;
|
| + if (descriptor_->GetSourceLocation(&location)) {
|
| + message_comments = BuildCommentsString(location);
|
| + } else {
|
| + message_comments = "";
|
| + }
|
| +
|
| + printer->Print(
|
| + "$comments$@interface $classname$ : GPBMessage\n\n",
|
| + "classname", class_name_,
|
| + "comments", message_comments);
|
| +
|
| + vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0);
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + const FieldDescriptor* field = descriptor_->field(i);
|
| + if (field->containing_oneof() != NULL) {
|
| + const int oneof_index = field->containing_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 (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
|
| + iter != oneof_generators_.end(); ++iter) {
|
| + (*iter)->GenerateClearFunctionDeclaration(printer);
|
| + }
|
| + printer->Print("\n");
|
| + }
|
| +
|
| + if (descriptor_->extension_count() > 0) {
|
| + printer->Print("@interface $classname$ (DynamicMethods)\n\n",
|
| + "classname", class_name_);
|
| + for (vector<ExtensionGenerator*>::iterator iter =
|
| + extension_generators_.begin();
|
| + iter != extension_generators_.end(); ++iter) {
|
| + (*iter)->GenerateMembersHeader(printer);
|
| + }
|
| + printer->Print("@end\n\n");
|
| + }
|
| +
|
| + for (vector<MessageGenerator*>::iterator iter =
|
| + nested_message_generators_.begin();
|
| + iter != nested_message_generators_.end(); ++iter) {
|
| + (*iter)->GenerateMessageHeader(printer);
|
| + }
|
| +}
|
| +
|
| +void MessageGenerator::GenerateSource(io::Printer* printer) {
|
| + if (!IsMapEntryMessage(descriptor_)) {
|
| + printer->Print(
|
| + "#pragma mark - $classname$\n"
|
| + "\n",
|
| + "classname", class_name_);
|
| +
|
| + printer->Print("@implementation $classname$\n\n",
|
| + "classname", class_name_);
|
| +
|
| + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
|
| + iter != oneof_generators_.end(); ++iter) {
|
| + (*iter)->GeneratePropertyImplementation(printer);
|
| + }
|
| +
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + field_generators_.get(descriptor_->field(i))
|
| + .GeneratePropertyImplementation(printer);
|
| + }
|
| +
|
| + scoped_array<const FieldDescriptor*> sorted_fields(
|
| + SortFieldsByNumber(descriptor_));
|
| + scoped_array<const FieldDescriptor*> size_order_fields(
|
| + SortFieldsByStorageSize(descriptor_));
|
| +
|
| + vector<const Descriptor::ExtensionRange*> sorted_extensions;
|
| + for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
|
| + sorted_extensions.push_back(descriptor_->extension_range(i));
|
| + }
|
| +
|
| + sort(sorted_extensions.begin(), sorted_extensions.end(),
|
| + ExtensionRangeOrdering());
|
| +
|
| + // TODO(thomasvl): Finish optimizing has bit. The current behavior is as
|
| + // follows:
|
| + // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index
|
| + // to the field's index in the list of fields.
|
| + // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to
|
| + // GPBNoHasBit because repeated fields & map<> fields don't use the has
|
| + // bit.
|
| + // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
|
| + // index that groups all the elements on of the oneof.
|
| + // So in has_storage, we need enough bits for the single fields that aren't
|
| + // in any oneof, and then one int32 for each oneof (to store the field
|
| + // number). So we could save a little space by not using the field's index
|
| + // and instead make a second pass only assigning indexes for the fields
|
| + // that would need it. The only savings would come when messages have over
|
| + // a multiple of 32 fields with some number being repeated or in oneofs to
|
| + // drop the count below that 32 multiple; so it hasn't seemed worth doing
|
| + // at the moment.
|
| + size_t num_has_bits = descriptor_->field_count();
|
| + size_t sizeof_has_storage = (num_has_bits + 31) / 32;
|
| + // Tell all the fields the oneof base.
|
| + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
|
| + iter != oneof_generators_.end(); ++iter) {
|
| + (*iter)->SetOneofIndexBase(sizeof_has_storage);
|
| + }
|
| + field_generators_.SetOneofIndexBase(sizeof_has_storage);
|
| + // Add an int32 for each oneof to store which is set.
|
| + sizeof_has_storage += descriptor_->oneof_decl_count();
|
| +
|
| + printer->Print(
|
| + "\n"
|
| + "typedef struct $classname$__storage_ {\n"
|
| + " uint32_t _has_storage_[$sizeof_has_storage$];\n",
|
| + "classname", class_name_,
|
| + "sizeof_has_storage", SimpleItoa(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");
|
| +
|
| + bool has_oneofs = oneof_generators_.size();
|
| + if (has_oneofs) {
|
| + printer->Print(
|
| + " static GPBMessageOneofDescription oneofs[] = {\n");
|
| + printer->Indent();
|
| + printer->Indent();
|
| + printer->Indent();
|
| + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
|
| + iter != oneof_generators_.end(); ++iter) {
|
| + (*iter)->GenerateDescription(printer);
|
| + }
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| + printer->Print(
|
| + " };\n");
|
| + }
|
| +
|
| + TextFormatDecodeData text_format_decode_data;
|
| + bool has_fields = descriptor_->field_count() > 0;
|
| + if (has_fields) {
|
| + // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription()
|
| + // wraps the fieldOptions's value of this structure in an CPP gate so
|
| + // they can be compiled away; but that still results in a const char* in
|
| + // the structure for a NULL pointer for every message field. If the
|
| + // fieldOptions are moved to a separate payload like the TextFormat extra
|
| + // data is, then it would shrink that static data shrinking the binaries
|
| + // a little more.
|
| + // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the
|
| + // structure because primitive types are always zero. If we add a second
|
| + // structure and a different initializer, we can avoid the wasted static
|
| + // storage for every field in a proto3 message.
|
| + printer->Print(
|
| + " static GPBMessageFieldDescription fields[] = {\n");
|
| + printer->Indent();
|
| + printer->Indent();
|
| + 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);
|
| + 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->Outdent();
|
| + printer->Outdent();
|
| + printer->Print(
|
| + " };\n");
|
| + }
|
| +
|
| + bool has_enums = enum_generators_.size();
|
| + if (has_enums) {
|
| + printer->Print(
|
| + " static GPBMessageEnumDescription enums[] = {\n");
|
| + printer->Indent();
|
| + printer->Indent();
|
| + printer->Indent();
|
| + for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
|
| + iter != enum_generators_.end(); ++iter) {
|
| + printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n",
|
| + "name", (*iter)->name());
|
| + }
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| + printer->Print(
|
| + " };\n");
|
| + }
|
| +
|
| + bool has_extensions = sorted_extensions.size();
|
| + if (has_extensions) {
|
| + printer->Print(
|
| + " static GPBExtensionRange ranges[] = {\n");
|
| + printer->Indent();
|
| + printer->Indent();
|
| + printer->Indent();
|
| + for (int i = 0; i < sorted_extensions.size(); i++) {
|
| + printer->Print("{ .start = $start$, .end = $end$ },\n",
|
| + "start", SimpleItoa(sorted_extensions[i]->start),
|
| + "end", SimpleItoa(sorted_extensions[i]->end));
|
| + }
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| + printer->Outdent();
|
| + printer->Print(
|
| + " };\n");
|
| + }
|
| +
|
| + map<string, string> vars;
|
| + vars["classname"] = class_name_;
|
| + vars["rootclassname"] = root_classname_;
|
| + vars["fields"] = has_fields ? "fields" : "NULL";
|
| + vars["fields_count"] =
|
| + has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
|
| + vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
|
| + vars["oneof_count"] =
|
| + has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
|
| + vars["enums"] = has_enums ? "enums" : "NULL";
|
| + vars["enum_count"] =
|
| + has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0";
|
| + vars["ranges"] = has_extensions ? "ranges" : "NULL";
|
| + vars["range_count"] =
|
| + has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0";
|
| + vars["wireformat"] =
|
| + descriptor_->options().message_set_wire_format() ? "YES" : "NO";
|
| +
|
| + if (text_format_decode_data.num_entries() == 0) {
|
| + 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"
|
| + " oneofs:$oneofs$\n"
|
| + " oneofCount:$oneof_count$\n"
|
| + " enums:$enums$\n"
|
| + " enumCount:$enum_count$\n"
|
| + " ranges:$ranges$\n"
|
| + " rangeCount:$range_count$\n"
|
| + " storageSize:sizeof($classname$__storage_)\n"
|
| + " wireFormat:$wireformat$];\n");
|
| + } else {
|
| + vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data());
|
| + printer->Print(
|
| + vars,
|
| + "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
|
| + " const char *extraTextFormatInfo = NULL;\n"
|
| + "#else\n"
|
| + " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
|
| + "#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
|
| + " GPBDescriptor *localDescriptor =\n"
|
| + " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
|
| + " rootClass:[$rootclassname$ class]\n"
|
| + " file:$rootclassname$_FileDescriptor()\n"
|
| + " fields:$fields$\n"
|
| + " fieldCount:$fields_count$\n"
|
| + " oneofs:$oneofs$\n"
|
| + " oneofCount:$oneof_count$\n"
|
| + " enums:$enums$\n"
|
| + " enumCount:$enum_count$\n"
|
| + " ranges:$ranges$\n"
|
| + " rangeCount:$range_count$\n"
|
| + " storageSize:sizeof($classname$__storage_)\n"
|
| + " wireFormat:$wireformat$\n"
|
| + " extraTextFormatInfo:extraTextFormatInfo];\n");
|
| + }
|
| + printer->Print(
|
| + " NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
|
| + " descriptor = localDescriptor;\n"
|
| + " }\n"
|
| + " return descriptor;\n"
|
| + "}\n\n"
|
| + "@end\n\n");
|
| +
|
| + for (int i = 0; i < descriptor_->field_count(); i++) {
|
| + field_generators_.get(descriptor_->field(i))
|
| + .GenerateCFunctionImplementations(printer);
|
| + }
|
| +
|
| + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
|
| + iter != oneof_generators_.end(); ++iter) {
|
| + (*iter)->GenerateClearFunctionImplementation(printer);
|
| + }
|
| + }
|
| +
|
| + for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
|
| + iter != enum_generators_.end(); ++iter) {
|
| + (*iter)->GenerateSource(printer);
|
| + }
|
| +
|
| + for (vector<MessageGenerator*>::iterator iter =
|
| + nested_message_generators_.begin();
|
| + iter != nested_message_generators_.end(); ++iter) {
|
| + (*iter)->GenerateSource(printer);
|
| + }
|
| +}
|
| +
|
| +} // namespace objectivec
|
| +} // namespace compiler
|
| +} // namespace protobuf
|
| +} // namespace google
|
|
|